Search code examples
djangodjango-admindjango-admin-actions

Django - add choice field to django admin list_filter


This is one of my django admin classes:

class InactiveSiteAdmin(SiteAdmin):
    change_list_template = 'admin/change_list_inactive.html'
    list_display = ('is_active', 'thumb', 'name', 'show_url', 'get_desc', 
        'keywords','category', 'subcategory', 'category1', 'subcategory1', 
        'group')
    fields = ('name', 'url', 'id', 'category', 'subcategory', 'category1',
          'subcategory1', 'description',
          'keywords', 'date', 'group', 'user', 'is_active', 'date_end',)
    readonly_fields = ('date', 'date_end', 'id')
    list_display_links = ('name',)
    actions = [activate_sites, activate_sites1, ]

    def get_queryset(self, request):
        return Site.objects.filter(is_active=False)

    def response_change(self, request, obj):
        return redirect('/admin/mainapp/site/{}/change/'.format(obj.id))

    def has_add_permission(self, request):
       return False

"activate_sites" action is for accepting selected object (make it visible) and for send confirmation email to obj.email (email field of selected object). I would like to add another field to list_display - for example "email_text" where superuser would choose correct text message (using choice field). Is it possible? I have 3 objects for example. I would like to give opportunity to activate all 3 objects and select different text messages to each object.

I tried adding something like this:

def email_send_field(self, request):
    MY_CHOICES = (
        ('A', 'Choice A'),
        ('B', 'Choice B'),
    )

    return(forms.ChoiceField(choices=MY_CHOICES))

but I get "" in list_display.


Solution

  • You can use the format_html method to insert your custom html and fetch the chosen value in the POST data.

    Just be careful to generate an unique name for each select element.

    In this example, it uses the object primary key:

    from django.utils.html import format_html
    
    MY_CHOICES = (
        ('msg1', 'Hello'),
        ('msg2', 'Hi'),
    )
    
    class InactiveSiteAdmin(SiteAdmin):
        list_display = list_display = ( ...,  'show_select')
         actions = ['send_email']
    
        def show_select(self, obj):
            html_select = "<select name='dropdown-obj-"+str(obj.pk)+"'>"
            for option in MY_CHOICES:
                html_select += "<option value='{}'>{}</option>".format(option[1], option[0])
            html_select += "</select> "
    
            return format_html(html_select)
    
        def send_email(self, request, queryset):
            for obj in queryset:
                obj_msg = request.POST['dropdown-obj-'+str(obj.pk)]
                #do something with the custom message