Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customize Django admin index page to display model objects

In the Django admin index page, the app and its models will normally be listed. How can the model objects also be listed in this index page? Instead of displaying just the app, I want to also display its model objects. How should it be customized?

enter image description here

like image 878
Nava Avatar asked Sep 21 '11 18:09

Nava


2 Answers

I wanted the same functionality for my site and added it by doing slight modifications to the core django system.

Step 1: First we need a way to indicate which models should have their properties listed. Add the following code to the models for which you want the instances listed (in models.py):

class Meta:
    list_instances = True

Step 2: We need to modify Django to recognize and read this new attribute. In core-django file: db/models/options.py, roughly at line 22 append 'list_instances' to DEFAULT_NAMES:

DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering',
             'unique_together', 'permissions', 'get_latest_by',
             'order_with_respect_to', 'app_label', 'db_tablespace',
             'abstract', 'managed', 'proxy', 'auto_created', 'list_instances')

and in the same file, roughly at line 52, create a default field for this attribute right after the other attributes :

self.list_instances = False

Step 3: We need to pass this information along to the template that generates the index page. In core-django file: contrib/admin/sites.py, inside index() method and inside the "if has_module_perms:" part, add the following code:

instances = []
if (model._meta.list_instances == True):
    instances = model_admin.queryset(None)

This will create the list of instances to show, but only if the list_instance attribute is set. In the same file, a few lines further down, append these values to the "model_dict" construct.

model_dict = {
    'name': capfirst(model._meta.verbose_name_plural),
    'admin_url': mark_safe('%s/%s/' % (app_label, model.    __name__.lower())),
    'perms': perms,
    'list_instances':model._meta.list_instances,
    'instances': instances,
}

Step 4: The final step is to modify the template to support this. Either edit the core-django file /contrib/admin/templates/admin/index.html or copy this file to the templates/admin/ directory of your specific app. Add a few lines after the standard code for generating rows to generate the "sub-rows" if applicable. Roughly at line 40, right between "/tr>" and "{% endfor %}":

{% if model.list_instances %}
    {% for instance in model.instances %}
    <tr>
        <td colspan="2" style="padding-left: 2em;">{{ instance }}</td>
        {% if model.perms.change %}
            <td><a href="{{ model.admin_url }}{{ instance.id }}/" class="changelink">{% trans 'Change' %}</a></td>
        {% else %}
            <td>&nbsp;</td>
        {% endif %}
    </tr>
    {% endfor %}
{% endif %}

This will cause the item to be listed with the name generated by the unicode() method in the model.

Step 5: Lo and behold! It should look something like this:

enter image description here

Edit: Optional Step 6: If you want the instance names to be clickable too, just change the template (index.html) and replace:

<td colspan="2" style="padding-left: 2em;">{{ instance }}</td>

with:

<td colspan="2" style="padding-left: 2em;">        
    {% if model.perms.change %}            
        <a href="{{ model.admin_url }}{{ instance.id}}">{{ instance }}</a>
    {% else %}
        {{ instance }}
    {% endif %}
</td>
like image 154
Setomidor Avatar answered Oct 07 '22 02:10

Setomidor


UPDATE Setomidor answer for django 10

Always great to come back to this clean solution!

step 2 - it is around line 125 (was 52)

step 3 - in sites.py - update the new method -

_build_app_dict

inside the for loop : for model, model_admin in models.items():

add step 3 as said around lines 430 and 460

instances = []


if (model._meta.list_instances == True):
    instances = model_admin.get_queryset(None)
like image 37
Ohad the Lad Avatar answered Oct 07 '22 02:10

Ohad the Lad