开发者

Extending Django Admin Templates - altering change list

A (not so) quick question about extending django admin templates.

I'm trying to change th开发者_JAVA技巧e result list (change list in django lingo) of a specific model by adding an intermediary row between the result rows (row1 and row2 classes) that contains some objects related to that object.

I searched the code but haven't found a way to do this. Any pointers are very much appreciated. Code will also help too.

PS: I know I should be designing my own interface, but this is an internal project and I don't have that much time to spare. Also, the django interface is really nice.

Thank you in advance.


To expand on Yuji's answer, here are some specifics on overriding change_list_results.html ...


Override changelist_view as described above in step 1, and also described here at djangoproject. Or auto-override by placing in the appropriate directory as in step 2 above. (Note that the step 2 path shown above is model-specific. App-specific would be /admin/<MyAppName>/change_list.html under any directory defined in the TEMPLATE_DIRS tuple.)

Or (perhaps easier) simply specify ModelAdmin.change_list_template as explained here with any discoverable template filename. (Although, if you retain the name change_list.html, be sure not to deposit directly into the /admin folder, else the extends tag will cause a recursion.)

class MyModelAdmin(admin.ModelAdmin):
    change_list_template = 'change_list.html' # definitely not 'admin/change_list.html'
    # ...

In your change_list.html template, have at a minimum

{% extends "admin/change_list.html" %}
{% load i18n admin_static admin_list %}
{% load myapptags %}

{% block result_list %}
  {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %}
  {% result_list cl %}
  {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %}
{% endblock %}

Create a /<MyAppName>/templatetags package (a directory containing __init__.py) with a file corresponding to the load tag above

# MyAppName/templatetags/myapptags.py

from django import template
from django.contrib.admin.templatetags.admin_list import result_list

register = template.Library()
register.inclusion_tag('my_change_list_results.html')(result_list)

Copy and edit Django's change_list_results.html (as e.g. my_change_list_results.html above) to use your added functionality.

Note that these steps do not include extra context for the template, but can easily be expanded as such. (My reason for doing this was to add classes for CSS and a leading <tbody> that was not sorted with the results list.)


ADDITIONAL:

To include extra context, change your templatetags module as follows:

# MyAppName/templatetags/myapptags.py

from django import template
from django.contrib.admin.templatetags.admin_list import result_list as admin_list_result_list

def result_list(cl):
    mycl = {'myextracontext': 'something extra'}
    mycl.update(foo_extra())
    mycl.update(admin_list_result_list(cl))
    return mycl

register = template.Library()
register.inclusion_tag('my_change_list_results.html')(result_list)

Then, the value of myextracontext or whatever foo_extra returns can be included in your results template (as e.g. {{ myextracontext }})


Step 1: Overriding changelist view:
You'll have to override a template as opposed to specifying one like you can with add_view / change_view.

First things first, override def changelist_view(self, request, extra_context=None): in your ModelAdmin. Remember to call super(foo, self).changelist_view(request, extra_context) and to return that.

Step 2: Overriding templates:
Next, override the app-specific changelist template at templates/admin/my_app/my_model/change_list.html (or not.. you can use a global changelist override too if you'd like).

Step 3: Copy result list functionality
I think you can either copy result_list functionality (define a new template tag) or fake it by copying and pasting the result_list function and template include into your view.

# django.contrib.admin.templatetags.admin_list
def result_list(cl):
    """
    Displays the headers and data list together
    """
    return {'cl': cl,
            'result_hidden_fields': list(result_hidden_fields(cl)),
            'result_headers': list(result_headers(cl)),
            'results': list(results(cl))}
result_list = register.inclusion_tag("admin/change_list_results.html")(result_list)

You can see the admin uses this admin/change_list_results.html template to render individual columns so you'll need to use one of the methods to replace this template tag.

Since it's looking for a global template, I wouldn't override it.

Either define a new tag w/ new template specifically for your view, or send result_list(cl) to your template directly and adopt the admin/change_list_results.html for use directly in your change_list.html template.


If you want a complete override of the admin_list template tag, here is my post in another thread. https://stackoverflow.com/a/55597294/11335685

I know it is not directly related to the change_list template, but the logic for it lays on the functions inside the admin_list template tag.

A disadvantage of that approach is i didn't find a way of overriding only specific function and get use of the other ones.

Still that was the only approach that was allowing me to not mess with the html templates and only alter the behavior of result_list function.

Hope that helps anyone.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜