Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Admin linking to related objects

My app has users who create pages. In the Page screen of the admin, I'd like to list the User who created the page, and in that list, I'd like the username to have a link that goes to the user page in admin (not the Page).

class PageAdmin(admin.ModelAdmin):     list_display = ('name', 'user', )     list_display_links = ('name','user',) admin.site.register(Page, PageAdmin) 

I was hoping that by making it a link in the list_display it would default to link to the actual user object, but it still goes to Page.

I'm sure I'm missing something simple here.

like image 575
Brenden Avatar asked Jun 20 '11 23:06

Brenden


2 Answers

Modifying your model isn't necessary, and it's actually a bad practice (adding admin-specific view-logic into your models? Yuck!) It may not even be possible in some scenarios.

Luckily, it can all be achieved from the ModelAdmin class:

from django.urls import reverse from django.utils.safestring import mark_safe       class PageAdmin(admin.ModelAdmin):     # Add it to the list view:     list_display = ('name', 'user_link', )     # Add it to the details view:     readonly_fields = ('user_link',)      def user_link(self, obj):         return mark_safe('<a href="{}">{}</a>'.format(             reverse("admin:auth_user_change", args=(obj.user.pk,)),             obj.user.email         ))     user_link.short_description = 'user'   admin.site.register(Page, PageAdmin) 

Edit 2016-01-17: Updated answer to use make_safe, since allow_tags is now deprecated.

Edit 2019-06-14: Updated answer to use django.urls, since as of Django 1.10 django.core.urls has been deprecated.

like image 181
WhyNotHugo Avatar answered Sep 25 '22 23:09

WhyNotHugo


Add this to your model:

  def user_link(self):       return '<a href="%s">%s</a>' % (reverse("admin:auth_user_change", args=(self.user.id,)) , escape(self.user))    user_link.allow_tags = True   user_link.short_description = "User"  

You might also need to add the following to the top of models.py:

  from django.template.defaultfilters import escape   from django.core.urls import reverse 

In admin.py, in list_display, add user_link:

list_display = ('name', 'user_link', ) 

No need for list_display_links.

like image 28
Udi Avatar answered Sep 25 '22 23:09

Udi