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?
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> </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:
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>
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With