[英]How to change User representation in Django Admin when used as Foreign Key?
I have a few models having User as Foreign Key.我有几个模型将用户作为外键。 The User list is displaying the username, but I'd like to customize it.用户列表显示用户名,但我想对其进行自定义。 Do I have to extend the User model with a custom model and write my own __str__
function?我是否必须使用自定义 model 扩展用户 model 并编写自己的__str__
function? Is there an easier way?有没有更简单的方法? I don't think you can use a callable for fieldset, right?我不认为你可以使用可调用的字段集,对吧?
I think __unicode__()
method is not the correct, you should use __str__()
method. 我认为__unicode__()
方法不正确,你应该使用__str__()
方法。
For Python 2.x
, __str__()
method will return str(bytes) and __unicode__()
method will return unicode (text). 对于Python 2.x
, __str__()
str __str__()
方法将返回str(bytes)和__unicode__()
方法将返回unicode(文本)。
The print statement and the str built-in call
__str__()
to determine the human-readable representation of an object. print语句和str内置调用__str__()
来确定对象的人类可读表示。 The unicode built-in calls__unicode__()
if it exists, and otherwise falls back to__str__()
and decodes the result with the system encoding. unicode内置调用__unicode__()
如果存在),否则返回__str__()
并使用系统编码解码结果。 Conversely, the Model base class automatically derives__str__()
from__unicode__()
by encoding to UTF-8. 相反,Model基类通过编码为UTF-8自动从__unicode__()
派生__str__()
。 read here complete 在这里阅读完整
But in Python 3.x
there is just __str__()
, no __unicode__()
method. 但是在Python 3.x
中只有__str__()
,没有__unicode__()
方法。
Django provides a simple way to define
__str__()
and__unicode__()
methods that work on Python 2 and 3: you must define a__str__()
method returning text and to apply the python_2_unicode_compatible () decorator. Django提供了一种简单的方法来定义适用于Python 2和3的__str__()
和__unicode__()
方法:您必须定义一个__str__()
方法返回文本并应用python_2_unicode_compatible ()装饰器。On Python 3, the decorator is a no-op. 在Python 3上,装饰器是无操作的。 On Python 2, it defines appropriate
__unicode__()
and__str__()
methods (replacing the original__str__()
method in the process). 在Python 2上,它定义了适当的__unicode__()
和__str__()
方法(替换了进程中的原始__str__()
方法)。
Here is an example from django docs. 这是django docs的一个例子。
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class MyClass(object):
def __str__(self):
return "Instance of my class"
SOLUTION : Decorate in the same way, as done above for your Class and in models.py
, add a method which will be get added to the User model. 解决方案:以相同的方式进行装饰,如上面针对您的类和models.py
所做的那样,添加一个将添加到User模型的方法。
from django.contrib.auth.models import User
def get_name(self):
return '{} {}'.format(self.first_name, self.last_name)
User.add_to_class("__str__", get_name)
ForeignKeys
in Django forms are represented by ModelChoiceFields
. Django表单中的ForeignKeys
由ModelChoiceFields
表示。 The ModelChoiceField
class has a label_from_instance
method, which decides how to render the choice. ModelChoiceField
类有一个label_from_instance
方法,该方法决定如何呈现选择。 So in order to change this representation in the Admin, you need to modify this form field. 因此,为了在Admin中更改此表示,您需要修改此表单字段。
Here is a simple example. 这是一个简单的例子。
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
field = super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
if db_field.name == "user":
field.label_from_instance = lambda u: "My Object #%i" % u.id
return field
You can change the string representation of the Django default User by overriding the User __unicode__
method. 您可以通过覆盖User __unicode__
方法来更改Django默认用户的字符串表示形式。 Add the code below somewhere in your app, perhaps in models.py 在应用中的某个位置添加代码,也许在models.py中
def custom_user_display(self):
return self.email + ', ' self.first_name # write your representation here
User.add_to_class("__unicode__", custom_user_display) # override the __unicode__ method
Assume you have a model like this 假设你有这样的模型
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True, verbose_name=_('user'), related_name='profile')
city = models.CharField(max_length=128, null=True, blank=True)
And you want to show the user's email instead of username or userid in admin page, then you can do something like this 并且您想在管理页面中显示用户的电子邮件而不是用户名或用户ID,然后您可以执行此类操作
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('get_user', 'city')
def get_user(self, obj):
return obj.user.email
get_user.short_description = 'User'
get_user.admin_order_field = 'user__id'
I had the same problem and I had to extend @Todor 's solution for many models and different apps.我遇到了同样的问题,我不得不为许多模型和不同的应用程序扩展@Todor 的解决方案。
In the end, it was better to override the default AdminSite and hook on register to customize the User form fields.最后,最好覆盖默认的 AdminSite并挂钩注册以自定义用户表单字段。
from django.contrib import admin
from django.contrib.admin import ModelAdmin
from django.contrib.auth import get_user_model
def user_admin_str(instance: get_user_model()) -> str:
return f"{instance.last_name}-chan"
def formfield_for_foreignkey(self, db_field, request, **kwargs):
field = super(ModelAdmin, self).formfield_for_foreignkey(
db_field, request, **kwargs)
if isinstance(db_field.related_model(), get_user_model()):
field.label_from_instance = user_admin_str
return field
def formfield_for_manytomany(self, db_field, request, **kwargs):
field = super(ModelAdmin, self).formfield_for_manytomany(
db_field, request, **kwargs)
if isinstance(db_field.related_model(), get_user_model()):
field.label_from_instance = user_admin_str
return field
class CustomAdminSite(admin.AdminSite):
def register(self, model_or_iterable, admin_class=None, **options):
setattr(admin_class, "formfield_for_foreignkey",
formfield_for_foreignkey)
setattr(admin_class, "formfield_for_manytomany",
formfield_for_manytomany)
super().register(model_or_iterable, admin_class=admin_class, **options)
No need to modify every ModelAdmin
then.然后不需要修改每个ModelAdmin
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.