簡體   English   中英

用作外鍵時如何更改 Django Admin 中的用戶表示?

[英]How to change User representation in Django Admin when used as Foreign Key?

我有幾個模型將用戶作為外鍵。 用戶列表顯示用戶名,但我想對其進行自定義。 我是否必須使用自定義 model 擴展用戶 model 並編寫自己的__str__ function? 有沒有更簡單的方法? 我不認為你可以使用可調用的字段集,對吧?

我認為__unicode__()方法不正確,你應該使用__str__()方法。

對於Python 2.x__str__() str __str__()方法將返回str(bytes)和__unicode__()方法將返回unicode(文本)。

print語句和str內置調用__str__()來確定對象的人類可讀表示。 unicode內置調用__unicode__()如果存在),否則返回__str__()並使用系統編碼解碼結果。 相反,Model基類通過編碼為UTF-8自動從__unicode__()派生__str__() 在這里閱讀完整

但是在Python 3.x中只有__str__() ,沒有__unicode__()方法。

Django提供了一種簡單的方法來定義適用於Python 2和3的__str__()__unicode__()方法:您必須定義一個__str__()方法返回文本並應用python_2_unicode_compatible ()裝飾器。

在Python 3上,裝飾器是無操作的。 在Python 2上,它定義了適當的__unicode__()__str__()方法(替換了進程中的原始__str__()方法)。

這是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"

解決方案:以相同的方式進行裝飾,如上面針對您的類和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)

Django表單中的ForeignKeysModelChoiceFields表示。 ModelChoiceField類有一個label_from_instance方法,該方法決定如何呈現選擇。 因此,為了在Admin中更改此表示,您需要修改此表單字段。

這是一個簡單的例子。

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

您可以通過覆蓋User __unicode__方法來更改Django默認用戶的字符串表示形式。 在應用中的某個位置添加代碼,也許在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

假設你有這樣的模型

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)

並且您想在管理頁面中顯示用戶的電子郵件而不是用戶名或用戶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'

我遇到了同樣的問題,我不得不為許多模型和不同的應用程序擴展@Todor 的解決方案。

最后,最好覆蓋默認的 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)

然后不需要修改每個ModelAdmin

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM