开发者

Django admin: hide read-only fields on new records?

I'm using the Django admin site with some readonly fields on records:

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')

This works great when editing records - the transactions_all_time field is read-only, just as I want.

However, when adding new records it behaves a bit oddly. I get a read-only section at the bottom of the page, which I can't edit and which is irrelevant at this point.

It would be much better if this field was not present at all when adding new records.

Is there any Django option for not displaying read-only fields while adding a new record? I know I can hack the CSS on add开发者_开发技巧_form.html to hide it, but is there a better way?

Thanks.


I had similar problem. Resolved it like this

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


Here's a DRY version of Kushal's solution:

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',)}
        ),
    )  

Note that this only works on the main form -- on an inline form, you're passed the main obj, not the inline obj.


I had a similar problem with a slightly different solution. I wanted to hide image previews (read only fields) from the 'new' form (the 'add' view) but display them when fetching a new object:

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

The #fields line shows the original fields. I admit this solution is not very 'DRY' but it's clear and simple.


another alternative is that you set the editable arg in the original Model.

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

your ModelAdmin will not show the field in edition, the field will get excluded.


This is how I ended up hiding the readonly_fields from the 'Add' page:

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

Without this 'foo' and 'bar' were shown when creating a new object and - despite being read-only - the page showed values generated by their respective field default functions but not the actual values that get saved which is confusing.

For example foo = models.DateTimeField(default=django.utils.timezone.now) was showing up with the time the 'Add' page was loaded, but the resultant created object had the time the form was submitted. Or a field with default=uuid.uuid4 shows a completely random value shown on the 'Add' page, which is then thrown away and replaced with another on save.

The documentation for readonly_fields says:

they are also excluded from the ModelForm used for creating and editing

yet this does not appear to be the case, despite the Django code appearing to suggest that they are - so if anyone can explain why I need to add the above get_exclude override to get this behaviour I would be interested to hear! Maybe 'excluded from the ModelForm' doesn't necessarily mean they aren't on the page?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜