Search code examples
djangodjango-admin

How to add a custom button in a registered model in django admin site


Can anyone guide me in the right direction on how to put a button next to the delete button here? I want to put a confirm and deny button next to it, that when I click it, it will send an email to the user that his/her application is accepted or denied. I've searched online for a solution and also read some similar questions here, but I am not sure whether or not those are right things to go to.


Solution

  • First make buttons for confirm and deny in list_page by writing confirmed() and denied() method , then you append your custom urls in admin urls by overriding get_urls() method and mapped those url to a view method confirmed_application() and denied_application().

    After processing your logic then you can redirect same change_list page.

    @admin.register(YourModel)
    class YourModelAdmin(admin.ModelAdmin):
        list_display = ['your_model_fields', 'confirmed', 'denied']
    
    
        def confirmed(self, obj):
            url = reverse('admin:confirm_url', kwargs={'id': obj.id})
            return format_html('<a class="button" href="{}">Confirm</a>', url)
    
        def denied(self, obj):
            url = reverse('admin:denied_url', kwargs={'id': obj.id})
            return format_html('<a class="button" href="{}">Deny</a>', url)
    
    
        def get_urls(self):
            urls = super().get_urls()
            custom_urls = [
                path('confirm/<int:id>', self.confirmed_application, name='confirm_url'),
                path('deny/<int:id>', self.denied_application, name='denied_url'),
            ]
            return custom_urls + urls
    
    
        def confirmed_application(self, request, id):
            # you get object_id you can do whatever you want
            # you can send a mail
    
            # after processed all logic you can redirect same modeladmin changelist page
            redirect_url = "admin:{}_{}_changelist".format(self.opts.app_label, self.opts.model_name)
            return redirect(reverse(redirect_url))
    
    
        def denied_application(self, request, id):
            # same as  confirmed_application do the logic
            ...