Opened 4 months ago
Closed 4 months ago
#35536 closed Cleanup/optimization (wontfix)
Incorrect represent empty list from JSONField in ChangeList
Reported by: | Denis Dudnik | Owned by: | nobody |
---|---|---|---|
Component: | contrib.admin | Version: | 5.0 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | yes | UI/UX: | no |
Description
I have a model like this:
class HistoryEvent(models.Model): name = models.TextField() value = JSONField(blank=True, null=True) edit_at = models.DateTimeField(default=timezone.now) edit_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
I have a number of records with values like these:
- Empty list - []
- Empty dict - {}
I have registered ModelAdmin like this:
@admin.register(HistoryEvent) class HistoryEventAdmin(admin.ModelAdmin): list_display = ("name", "value")
When I open a page with data in the admin panel, I find some things:
- Empty dict represents as a text like this"{}"
- Empty list represents as an empty text like this"" while I wait "[]"
The problem could be here:
django 5.0.6
file: django/contrib/admin/utils.py
def display_for_field(value, field, empty_value_display): from django.contrib.admin.templatetags.admin_list import _boolean_icon if getattr(field, "flatchoices", None): try: return dict(field.flatchoices).get(value, empty_value_display) except TypeError: # Allow list-like choices. flatchoices = make_hashable(field.flatchoices) value = make_hashable(value) return dict(flatchoices).get(value, empty_value_display) # BooleanField needs special-case null-handling, so it comes before the # general null test. elif isinstance(field, models.BooleanField): return _boolean_icon(value) elif value is None: return empty_value_display elif isinstance(field, models.DateTimeField): return formats.localize(timezone.template_localtime(value)) elif isinstance(field, (models.DateField, models.TimeField)): return formats.localize(value) elif isinstance(field, models.DecimalField): return formats.number_format(value, field.decimal_places) elif isinstance(field, (models.IntegerField, models.FloatField)): return formats.number_format(value) elif isinstance(field, models.FileField) and value: return format_html('<a href="{}">{}</a>', value.url, value) elif isinstance(field, models.JSONField) and value: try: return json.dumps(value, ensure_ascii=False, cls=field.encoder) except TypeError: return display_for_value(value, empty_value_display) else: return display_for_value(value, empty_value_display)
I think this line:
elif isinstance(field, models.JSONField) and value:
should be like this:
elif isinstance(field, models.JSONField):
because of empty list could be dumps and shouldn't be joined.
Join for empty list return empty string, and this looks confusion.
Before (Now)
NAME VALUE TEST
After
NAME VALUE TEST []
Note:
See TracTickets
for help on using tickets.
I believe this is happening because
JSONField
uses the default set ofempty_values
which include{}
and[]
Since this ticket #19997, you can customise the empty values of forms fields and, due to the test written in 4cccb85e292fea01b3459cd97d751ed35179a7b7, I think this looks intentional.
I think we need some more opinions before we would make a change here.
If you think the default for
JSONField
should be updated, perhaps you can propose this on the forum and see if other people agree with you?