Proper way to handle custom submit button at django custom model admin add page

2.7k Views Asked by At

I want to add an extra button at submit_line.html that does exactly the same thing as submit but it sets certain field to something else while sending post request to server.

Say I have a blog as model, I want to add "save as draft" as button.

My submit_line.html looks like this:

{% load i18n admin_urls %}
<div class="submit-row">
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save" />{% endif %}

{% if show_save_as_draft %}<input type="submit" value="save_as_draft" class="default" name="_save" />{% endif %}


{% if show_delete_link %}
    {% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
    <p class="deletelink-box"><a href="{% add_preserved_filters delete_url %}" class="deletelink">{% trans "Delete" %}</a></p>
{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" />{% endif %}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" />{% endif %}
</div>

Now I don't understand how it is making this request, so I can't modify it, so please help me regarding this.

1

There are 1 best solutions below

2
On BEST ANSWER

First, give your button a unique name:

{% if show_save_as_draft %}
    <input type="submit" 
           value="{% trans 'Save as draft' %}" 
           class="default" 
           name="_save_as_draft" />
{% endif %}

Then, in your ModelAdmin you can override the save_model() method:

class MyModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        if '_save_as_draft' in request.POST.keys():
            # Do your custom stuff, e.g.
            obj.is_draft = True

        # Let Django do its defaults.
        super(MyModelAdmin, self).save_model(request, obj, form, change)        

One important thing is that save_model() has to save the instance. This means if the method or one of its if/else branches doesn't call super you need to make sure to call obj.save() somewhere.

There are many more possibilities to customize the workflow based on what button has been clicked. The gist is that this information is available in the request instance, which is accessible in most related ModelAdmin methods.

E.g. another interesting use case is redirecting the user to somewhere else after hitting the Save as draft button, which is possible by overriding response_add() and response_change().