简体   繁体   English

用作外键时如何更改 Django Admin 中的用户表示?

[英]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表单中的ForeignKeysModelChoiceFields表示。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM