Django 管理员覆盖显示的字段值

问题描述 投票:0回答:4

我有以下型号:

class Model(models.Model):

    creator = models.ForeignKey(User,related_name='com_creator',on_delete=models.SET_NULL, blank=True, null=True)
    username = models.CharField(max_length=60,default="")
    created = models.DateTimeField(auto_now_add=True)
    body = models.TextField(max_length=10000,default=" ")
    subtype = models.CharField(_("SubType"),max_length=100)
    typ = models.CharField(_("Type"),max_length=50)
    plus = models.ManyToManyField(User,related_name='com_plus', verbose_name=_('Plus'), blank=True)
    is_anonymous = models.BooleanField(_('Stay Anonymous'), blank=True, default=False)

typ和subtype中的值是代码,例如:“6_0_p”,(因为原始值长得可笑,所以我使用代码和字典来翻译为人类可读的形式)。

问题:如何在 django admin 中拦截这些值并将其转换为人类可读的形式?

这是我到目前为止尝试过的:

class ModelAdmin(admin.ModelAdmin):
    model = Model
    extra = 1
    exclude = ("username","creator","plus" ) 
    readonly_fields = ('subtype','typ','is_anonymous','created')
    fields = ('body','subtype','typ')

    def typ(self, obj):
        self.typ = "ppp"
        obj.typ = "ppp"
        return "pppp"

我尝试返回对象、自身和其他一些值。我还尝试在不使用可调用函数的情况下设置该值,只需声明“typ='xxx'”。没有什么。我可能不明白这整件事是如何运作的......

任何想法将不胜感激。

django django-models django-admin
4个回答
9
投票

您需要创建一个与您的方法名称相对应的

readonly_field
,然后从该方法返回任何内容。

文档在这里: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields

class MyAdmin(admin.ModelAdmin):
    readonly_fields = ('my_custom_field',)

    def my_custom_field(self, obj):
        return 'Return Anything Here'

5
投票

我认为您的代码不起作用,因为 method 名称与字段相同。

您必须更改字段的名称,例如字段元组中的 _typ,然后添加一个名为 _typ 的方法,该方法返回任何内容或某些 obj attr。

即:

class ModelAdmin(admin.ModelAdmin):
    model = Model
    extra = 1
    exclude = ("username","creator","plus" ) 
    readonly_fields = ('subtype','typ','is_anonymous','created')
    fields = ('body','subtype','_typ')

    def _typ(self, obj):
        return "pppp"

2
投票

在 Django 4 及更高版本中,您可以轻松添加自定义(只读)字段,如下所示:

class FooAdmin(admin.ModelAdminAbstractAdmin):
    readonly_fields = [
        '_dynamic_field',
    ]
    fieldsets = [
        ('Form', {
            'fields': (
                '_dynamic_field',
            ),
            'classes': ('form-group',)
        }),
    ]

    def _dynamic_field(self, obj=None):
        if obj is not None:
            return 'Bar'
        return "Foo"

    # to change the label
    _dynamic_field.__name__ = "Dynamic field label"

如您所见,该字段也需要位于

readonly_fields
fieldsets
中。


0
投票

choices
允许这样做。它们是https://docs.djangoproject.com/en/5.0/ref/models/fields/#choices:

采用下面描述的格式的映射或迭代,用作该字段的选择。如果给出选择,它们将通过模型验证强制执行,并且默认表单小部件将是包含这些选项的选择框,而不是标准文本字段。

如果给出了映射[或可迭代],则键[或第一个]元素是要在模型上设置的实际值,第二个元素是人类可读的名称。

适应 https://docs.djangoproject.com/en/5.0/ref/models/fields/#enumeration-types 适应您的问题:

class Model(models.Model):
    class MyTypes(models.TextChoices):
        T6_0_P = '6_0_p', 'original value that is ridiculously long'
        T6_0_Q = '6_0_q', 'other original value that is ridiculously long'
        T7_0_P = '7_0_p', 'yet another original value that is ridiculously long'

    class MySubTypes(models.TextChoices):
        ST6_0_P = 's6_0_p', 'original value that is ridiculously long'
        ST6_0_Q = 's6_0_q', 'other original value that is ridiculously long'
        ST7_0_P = 's7_0_p', 'yet another original value that is ridiculously long'

    creator = models.ForeignKey(
        User, related_name='com_creator',on_delete=models.SET_NULL, blank=True, null=True
    )
    username = models.CharField(max_length=60, default="")
    created = models.DateTimeField(auto_now_add=True)
    body = models.TextField(max_length=10000, default=" ")
    subtype = models.CharField(_("SubType"), choices=MySubTypes, max_length=100)
    typ = models.CharField(_("Type"), choices=MyTypes, max_length=50)
    plus = models.ManyToManyField(
        User,related_name='com_plus', verbose_name=_('Plus'), blank=True
    )
    is_anonymous = models.BooleanField(_('Stay Anonymous'), blank=True, default=False)
© www.soinside.com 2019 - 2024. All rights reserved.