[英]Making Django Readonly ForeignKey Field in Admin Render as a Link
I have a model exposed in Django's admin, which uses ModelAdmin's readonly_fields list to show a "user" field, which is a ForiegnKey linking to Django's User model.我在 Django 的管理员中公开了一个模型,它使用 ModelAdmin 的 readonly_fields 列表来显示“用户”字段,这是一个链接到 Django 用户模型的 ForiegnKey。 By default, readonly_fields causes this field to be rendered as simple text containing the user's email (eg
someuser@domain.com
).默认情况下, readonly_fields 使此字段呈现为包含用户电子邮件的简单文本(例如
someuser@domain.com
)。 How would I change this to render as a link to the associated admin page for that user?我将如何更改它以呈现为该用户的关联管理页面的链接? (eg
<a href="/admin/auth/user/123/">someuser@domain.com</a>
) (例如
<a href="/admin/auth/user/123/">someuser@domain.com</a>
)
Digging into the source code, I found you can essentially define your own fields as methods within your ModelAdmin subclass, and you can get the field to render as a link by simply returning the link html from the method. 深入研究源代码,我发现你基本上可以将自己的字段定义为ModelAdmin子类中的方法,并且只需从方法中返回链接html即可将字段呈现为链接。
eg 例如
from django.contrib import admin
from django.utils.safestring import mark_safe
from django.core import urlresolvers
class MyModelAdmin(admin.ModelAdmin):
readonly_fields = ['user_link']
def user_link(self, obj):
change_url = urlresolvers.reverse('admin:auth_user_change', args=(obj.user.id,))
return mark_safe('<a href="%s">%s</a>' % (change_url, obj.user.email))
user_link.short_description = 'User'
Cerin's answer does not work in my Django 1.8 project, because readonly_fields should not contain string 'user_link', but a reference to defined function: Cerin的答案在我的Django 1.8项目中不起作用,因为readonly_fields不应该包含字符串'user_link',而是对定义函数的引用:
class ProfileAdmin(admin.ModelAdmin):
# https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display
def user(obj):
change_url = reverse('admin:auth_user_change', args=(obj.user.id,))
return mark_safe('<a href="{0}">{1}</a>'.format(change_url, obj.user.email))
user.short_description = 'Edit linked user'
raw_id_fields = ('user',)
list_display = (user, 'last_name', 'first_name', 'specialization',)
list_display_links = ('first_name', 'last_name', ,)
readonly_fields = (user, 'user',)
Note that user(obj) overrides both single model edit and model list display for Profile.user field. 请注意,user(obj)会覆盖Profile.user字段的单个模型编辑和模型列表显示。 Note also that readonly_fields uses both user and 'user', one renders linked email, another one user name.
另请注意,readonly_fields同时使用用户和'user',一个呈现链接的电子邮件,另一个用户名。
I created some mixin我创建了一些 mixin
# base.py
from django.urls import reverse
from django.utils.html import format_html
def base_method_factory(field_name):
def base_method(obj):
try:
model = getattr(
obj,
field_name,
)
app_label = model._meta.app_label
model_name = model._meta.model_name
except AttributeError as e:
return None
return format_html(
'<a href="{0}">{1}</a> ',
reverse('admin:%s_%s_change' % (app_label, model_name), args=[model.id]),
str(model),
)
return base_method
class ReadonlyLinkMixin(object):
def __init__(self, *args, **kwargs):
self.create_linked_fields()
super().__init__(*args, **kwargs)
def create_linked_fields(self):
linked_fields = filter(lambda name: name.endswith('_linked'), self.readonly_fields)
for linked_field in linked_fields:
setattr(
self,
linked_field,
base_method_factory(linked_field.rpartition('_')[0])
)
# models.py
class SomeModel(models.Model):
...
task = models.FK(...)
# some_app_admin.py
@admin.register(SomeModel)
class SomeModelAdmin(
ReadonlyLinkMixin,
admin.ModelAdmin,
):
fields = (
...
'task_linked',
)
readonly_fields = (
...
'task_linked',
)
So in admin page it will look as linked string所以在管理页面中它看起来像链接的字符串
Hope this will be helpful!希望这会有所帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.