Django管理界面:如何在新记录中隐藏只读字段?

6

我正在使用Django管理站点,并在记录上使用一些只读字段:

class BookAdmin(admin.ModelAdmin):
    fieldsets = [
    (None, {'fields': ['title', 'library_id', 'is_missing', \
                       'transactions_all_time']}),
    ]
    readonly_fields = ['transactions_all_time',]
    list_display = ('library_id', 'author', 'title')

编辑记录时这个很好用——transactions_all_time字段是只读的,正如我所希望的那样。

但是,在添加新记录时,它的行为有点奇怪。我在页面底部得到了一个只读区域,无法编辑,这对于此时来说是无关紧要的。

如果在添加新记录时不显示该字段,将会更好。

是否有 Django 选项可以在添加新记录时不显示只读字段?我知道我可以在 add_form.html 上hack CSS 来隐藏它,但是否有更好的方法呢?

谢谢。

5个回答

15

我遇到了类似的问题。像这样解决了它

class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = ('field_one',)
    def get_readonly_fields(self, request, obj=None):
        if obj: # Editing
            return self.readonly_fields
        return ()

4
这里是Kushal方案的DRY版本:

def get_fieldsets(self, request, obj=None):
    def if_editing(*args):
        return args if obj else ()
    return (
        (None, {
            'classes': ('wide',),
            'fields': if_editing('admin_thumb', 'admin_image',) +
                      ('original_image', 'user', 'supplier', 'customer', 'priority',)}
        ),
    )  

请注意,此方法仅适用于主表单 - 在内嵌表单中,您将传递主对象而不是内嵌对象。

2

我曾经遇到过类似的问题,不过解决方案略有不同。我想要在“新建”表单(即“添加”视图)中隐藏图像预览(只读字段),但在获取新对象时显示它们:

class PhotoAdmin(admin.ModelAdmin):
readonly_fields = ('admin_image', 'admin_thumb', )
search_fields = ('filename', 'user', 'supplier', 'customer')
list_display= ('admin_thumb','filename', 'user', 'supplier', 'customer')
#fields = ('admin_thumb', 'admin_image', 'original_image', 'user', 'supplier', 'customer')


def get_fieldsets(self, request, obj=None):
    fieldset_existing = (
        (None, {
            'classes': ('wide',),
            'fields': ('admin_thumb', 'admin_image',
                'original_image', 'user', 'supplier', 'customer', 'priority',)}
        ),
    )
    fieldset_new = (
        (None, {
            'classes': ('wide',),
            'fields': ('original_image', 'user', 'supplier', 'customer', 'priority',)}
        ),
    )
    if obj: # Editing
        return fieldset_existing
    return fieldset_new

#fields 行显示原始字段。我承认这个解决方案不是非常“DRY”,但它清晰简单。


0

另一种选择是在原始模型中设置editable参数。

class Book(models.Model):
    transactions_all_time = models.BooleanField(editable=False)

您的ModelAdmin将不会在编辑中显示该字段,该字段将被排除。


他希望在编辑表单上该字段是只读的,但不完全排除它。 - Yuji 'Tomita' Tomita

0
这就是我最终如何隐藏“添加”页面中的readonly_fields
class MyAdmin(admin.ModelAdmin):

    readonly_fields = ['foo', 'bar']

    def get_exclude(self, request, obj=None):
        exclude = super().get_exclude(request, obj)
        if obj is None:
            # Adding a new one
            exclude = (exclude or []) + self.readonly_fields
        return exclude

没有这个设置,当创建一个新对象时,'foo'和'bar'会显示出来,尽管它们是只读的,页面上显示的是它们各自字段的默认值函数生成的值,而不是实际保存的值,这很令人困惑。

例如,foo = models.DateTimeField(default=django.utils.timezone.now)会显示加载'Add'页面时的时间,但是创建的对象却有表单提交时的时间。或者一个带有default=uuid.uuid4的字段,在'Add'页面上显示一个完全随机的值,然后在保存时被替换为另一个值。

readonly_fields的文档中说:

它们也被排除在用于创建和编辑的ModelForm之外

然而,尽管Django代码似乎表明它们是这样的,但事实并非如此 - 因此,如果有人能解释为什么我需要添加上述get_exclude覆盖以获得这种行为,我会很感兴趣!也许“从ModelForm中排除”并不一定意味着它们不在页面上?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接