How can I ask for user input with an action in django admin?
Asked Answered
E

2

11

In my code, I am writing an action for grouping, I would like to ask the user how many people would they like per group and then respond with an alert box that says something along the lines of you have 4 groups, based on user input. How do I do this in django admin, how do I create some kind of pop up that asks for the amount of people that they would like to put in a group? (I'm trying to achieve this with an action)

admin.py:

 Def howmany (modeladmin, request, queryset):
      people = queryset.count()
      amount_per = [the number that the user inputs]
      Amount_of_groups = people/amount_per
Edlin answered 10/8, 2014 at 23:2 Comment(0)
F
8

admin.py Something like:

class MyAdmin(admin.ModelAdmin):

    def howmany(modeladmin, request, queryset):
        people = queryset.count()
        amount_per = [the number that the user inputs]
        Amount_of_groups = people/amount_per

        if 'apply' in request.POST:
            form = AmountPerForm(request.POST)

            if form.is_valid():
                amount_per = form.cleaned_data['amount_per']
                self.message_user(request, u'You selected - %s' % amount_per)
            return HttpResponseRedirect(request.get_full_path())
        else:
            form = AmountPerForm()

        return render(request, 'admin/amount_per_form.html', {
            'items': queryset.order_by('pk'),
            'form': form,
            'title': u'Your title'
            })

File "admin/amount_per_form.html" contains something like:

 {% extends 'admin/base_site.html' %}

 {% block content %}
 <form action="" method="post">
    {% csrf_token %}
    <input type="hidden" name="action" value="howmany" />
    {% for item in items %}
    <input type="hidden" name="_selected_action" value="{{ item.pk }}"/> {# thanks to @David Hopkins for highligting it #}
    {% endfor %}

    {{ form }}
    <p>Apply for:</p>
    <ul>{{ items|unordered_list }}</ul>
    <input type="submit" name="apply" value="Apply" />
 </form>
 {% endblock %}
Fen answered 11/8, 2014 at 7:13 Comment(2)
Beware that when iterating through the item list in form you need to include hidden _selected_action field. Without it when you submit you will not be brought to your action, just back to the admin list, and your action will not succeed (using Django version 2.2). Example: <input type="hidden" name="_selected_action" value="{{ item.pk }}"/>.... I just wasted an hour using this solution 😞 – Enswathe
Great! Thanks for the advice I was falling in exactly the same problem! – Hatty
L
15

A more simplified and better approach I found here:

You just need to create an Action Form like this.

from django.contrib.admin.helpers import ActionForm
from django import forms


class XForm(ActionForm):
    x_field = forms.ModelChoiceField(queryset=Status.objects.all(), required=False)

Now, define that XForm in your admin.py

class ConsignmentAdmin(admin.ModelAdmin):

    action_form = XForm
    actions = ['change_status']

    def change_status(modeladmin, request, queryset):
        print(request.POST['x_field'])
        for obj in queryset:
            print(obj)
    change_status.short_description = "Change status according to the field"
Lafferty answered 29/8, 2020 at 8:13 Comment(2)
this should be the accepted solution. It is far more elegant, and the currently accepted answer is difficult to get working. – Cobaltic
This answer is clearly the way of doing this. Thank you for sharing. – Lave
F
8

admin.py Something like:

class MyAdmin(admin.ModelAdmin):

    def howmany(modeladmin, request, queryset):
        people = queryset.count()
        amount_per = [the number that the user inputs]
        Amount_of_groups = people/amount_per

        if 'apply' in request.POST:
            form = AmountPerForm(request.POST)

            if form.is_valid():
                amount_per = form.cleaned_data['amount_per']
                self.message_user(request, u'You selected - %s' % amount_per)
            return HttpResponseRedirect(request.get_full_path())
        else:
            form = AmountPerForm()

        return render(request, 'admin/amount_per_form.html', {
            'items': queryset.order_by('pk'),
            'form': form,
            'title': u'Your title'
            })

File "admin/amount_per_form.html" contains something like:

 {% extends 'admin/base_site.html' %}

 {% block content %}
 <form action="" method="post">
    {% csrf_token %}
    <input type="hidden" name="action" value="howmany" />
    {% for item in items %}
    <input type="hidden" name="_selected_action" value="{{ item.pk }}"/> {# thanks to @David Hopkins for highligting it #}
    {% endfor %}

    {{ form }}
    <p>Apply for:</p>
    <ul>{{ items|unordered_list }}</ul>
    <input type="submit" name="apply" value="Apply" />
 </form>
 {% endblock %}
Fen answered 11/8, 2014 at 7:13 Comment(2)
Beware that when iterating through the item list in form you need to include hidden _selected_action field. Without it when you submit you will not be brought to your action, just back to the admin list, and your action will not succeed (using Django version 2.2). Example: <input type="hidden" name="_selected_action" value="{{ item.pk }}"/>.... I just wasted an hour using this solution 😞 – Enswathe
Great! Thanks for the advice I was falling in exactly the same problem! – Hatty

© 2022 - 2024 β€” McMap. All rights reserved.