5

I want to override submit_line.html for a single model or a single app (either will work - the app has just one model). I see in the docs I cannot do that (https://docs.djangoproject.com/en/1.5/ref/contrib/admin/#templates-which-may-be-overridden-per-app-or-model)

Is there some way to test for what model or app the template is being called for so I can add some conditional behaviour? Or perhaps is there some way to have a different template used in place of submit_line.html for a specific app or model?

mishbah's answer has solved my initial problem, but now I am facing another issue - when my code is done, something runs that add the row. I don't want that to happen.

Here's what I am trying to accomplish:

  1. User clicks add button
  2. Add object page is shown with my custom button
  3. When my button is clicked I execute an ajax call and display the results below the add div, and this page is shown until the user clicks a button.

This all works - my only issue is that a rows get added to the database - I would somehow like to prevent that from happening.

Here is my code:

On the main admin page I have just the add button:

enter image description here

Here is my change_form.html:

{% extends "admin/change_form.html" %}

{% block submit_buttons_bottom %}

<style type="text/css">
    #id_tool_configuration {
        white-space: pre-wrap;
    }   
</style>

<div class="submit-row">
    <input value="Configure" class="default" name="configure" onclick="configureTools(document.getElementById('id_tool_configuration').value); " />
</div>

<script src="/static/scripts/jquery-1.7.js" type="text/javascript"></script>

<script type="text/javascript">
    function configureTools(tcd) {
        var toolConfigData = tcd;
        var request = new XMLHttpRequest();
        var params = 'toolConfigData='+encodeURIComponent(toolConfigData);
        request.open('GET', '{% url 'motor.configuration.views.configure' %}?'+params);
        request.setRequestHeader("Content-type", "text/plain; charset=utf-8");

        request.onreadystatechange = function() {
            if (request.readyState == 4) {
                if (request.status == 200) {
                    status = 'Confguration results:';
                }
                else {
                    status = 'Confguration failed';
                }

                $('.submit-row').after(
                    $('<span />')
                    .html('<pre> ' + status + '\n' + request.responseText + '</pre>')
                    .after($('<button />').text('Return').click('function () { return; }'))
                );
            }
        };

        request.send(null);
        return false;
    };
</script>

{% endblock %}

Larry Martell
  • 3,526
  • 6
  • 40
  • 76

2 Answers2

8

It is possible to override submit-row. Simply override the change_form template in your modeladmin:

class YourModelAdmin(admin.ModelAdmin):
    change_form_template = 'path/to/custom/change_form.html'

And in your custom change_form.html, you'll need to:

{% extends "admin/change_form.html" %}

and override the submit_buttons_bottom block:

{% block submit_buttons_bottom %}
     {# custom submit row goes here #}
{% endblock %} 

You could define your own custom submit_row templatetag, use the original templatetag for your inspiration:

See https://github.com/django/django/blob/1101467ce0756272a54f4c7bc65c4c335a94111b/django/contrib/admin/templatetags/admin_modify.py#L24

Also see this answer for the solution on how to determine the path of the template.

Community
  • 1
  • 1
mishbah
  • 5,487
  • 5
  • 25
  • 35
  • This works great. Thanks! But after my custom code runs it still runs the default add code. How can I prevent that? – Larry Martell Apr 05 '15 at 12:36
  • What do you mean by default add code? Can you add sample code .. for what you've done so far and what exactly you trying to achieve with custom submit row.. – mishbah Apr 05 '15 at 23:50
  • My override of submit_buttons_bottom has one button that invokes some custom code that does not add the row to the database. When my code is done, something runs that add the row. I don't want that to happen. Tomorrow I will post my code. I will also see if I can find out with the debugger what is running that is adding the row. – Larry Martell Apr 06 '15 at 01:54
  • I have added code and said what I am trying to achieve. Thanks for taking the time to look at it. – Larry Martell Apr 07 '15 at 17:44
  • I solved my problem with the add page returning to the main admin page by removing type="submit" from my custom button. I then added another button they can click to return. I've updated my code to show that. I still have the issue with the row getting added. I'd like to fix that, but since it's just a dummy table I can live with it. – Larry Martell Apr 08 '15 at 22:40
2

It is also possible to override/extend the innermost {% block submit-row %} like so:

{% block submit-row %}
    {% if extra_button_allowed %}
        <input type="submit" value="Get me tea" name="_get_tea" />
    {% endif %}
    {{ block.super }}
{% endblock %}

This way you maintain the original behaviour of the 'Save' buttons.

The submit-row block comes from the django/contrib/admin/templates/admin/submit_line.html template.

Peter Kilczuk
  • 589
  • 2
  • 7
  • 19
  • There is a block called "submit-row", but it is used in a template, that is then used to render a template tag, so it won't be accessible to the template of the web page. Unless I don't know about something. If that's the case, let me know and I'll upvote. – dotz Aug 21 '21 at 13:41
  • 1
    It won't be accessible in that template, however, the template tag is rendered through `InclusionAdminNode` which looks for `'admin/%s/%s/%s' % (app_label, object_name, self.template_name)` and so on, so you can definitely customize this on a per-app/per-model basis. – Peter Kilczuk Aug 23 '21 at 17:14
  • 1
    Note that this is the more clean solution; practical implementation details in [this gist](https://gist.github.com/squio/3619c4dfe079281ac722aa762e33be38) – jlapoutre Jan 19 '22 at 14:19