Как создать ссылку на другой объект из представления администратора Django?

#django #django-admin

#django #django-admin

Вопрос:

Я создал пользовательский класс администратора для отображения комментариев администратора в моем приложении Django. Что я хотел бы сделать, так это чтобы элементы в разделе «Идентификатор объекта» ссылались на страницу редактирования объекта их соответствующих объектов. Как бы мне этого добиться?

Мои комментарии администратора:

 class MyCommentsAdmin(admin.ModelAdmin):
    fieldsets = (
        (_('Content'),
           {'fields': ('user', 'user_name', 'user_email', 'user_url', 'comment')}
        ),
        (_('Metadata'),
           {'fields': ('submit_date', 'ip_address', 'is_public', 'is_removed')}
        ),
     )

    list_display = ('id', 'name', 'comment', 'content_type', 'object_pk', 'ip_address', 'submit_date', 'is_public', 'is_removed')
    list_filter = ('submit_date', 'site', 'is_public', 'is_removed')
    date_hierarchy = 'submit_date'
    list_display_links = ('id','comment',)
    ordering = ('-submit_date',)
    raw_id_fields = ('user',)
    search_fields = ('comment', 'user__username', 'user_name', 'user_email', 'ip_address')

admin.site.unregister(Comment)
admin.site.register(Comment, MyCommentsAdmin)
  

Спасибо!!

Ответ №1:

Определите пользовательский метод в классе admin и ссылайтесь на него в своем list_display кортеже.

 from django.core.urlresolvers import reverse
class MyCommentsAdmin(admin.ModelAdmin):

    list_display = ('id', 'name', 'comment', 'content_type', 'object_link', 'ip_address', 'submit_date', 'is_public', 'is_removed')
    list_select_related = True

    def object_link(self, obj):
        ct = obj.content_type
        url = reverse('admin:%s_%s_change' % (ct.app_label, ct.model), args=(obj.id,)) 
        return '<a href="%s">%s</a>' % (url, obj.id)
    object_link.allow_tags = True
  

Примечание, которое я добавил list_select_related=True , поскольку метод object_link ссылается на модель content_type, в противном случае это вызвало бы целую кучу дополнительных запросов.

Комментарии:

1. Спасибо. Где-то здесь есть небольшая ошибка. id Возвращаемый идентификатор не является идентификатором объекта, а вместо этого является собственным идентификатором комментария. Как мне это исправить?

2. Я изменил obj.id на obj.object_pk . Спасибо!

3. Я использую Django 1.7, и мне нужно было изменить obj.content_type на obj._meta и изменить ct.model на ct.model_name .

4. На самом деле для более поздних версий, чем 1.7, вам также нужно сделать то же самое. Также mark_safe_decorator вместо object_link.allow_tags = True , если вы используете Django 2.

Ответ №2:

Это был хороший ответ, но он значительно изменился. Этот ответ больше применим к Django 3.2.3 .

 from django.urls import reverse
from django.utils.safestring import mark_safe

class MyCommentsAdmin(admin.ModelAdmin):

    list_display = (
        'id', 'name', 'comment', 'content_type', 'object_link', 'ip_address',
        'submit_date', 'is_public', 'is_removed'
    )

    def object_link(self, obj):
        app_label = obj._meta.app_label
        model_label = obj._meta.model_name
        url = reverse(
            f'admin:{app_label}_{model_label}_change', args=(obj.id,)
        ) 
        return mark_safe(f'<a href="{url}">{obj.id}</a>')