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?
精彩评论