Skip to content

Commit e51f7a0

Browse files
Merge pull request #30 from uptick/date-format
feat: format dates when getting extrafields for display
2 parents a0b20ab + 135c71c commit e51f7a0

File tree

3 files changed

+121
-6
lines changed

3 files changed

+121
-6
lines changed

example/library/tests.py

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def test_create_field(self):
2727
)
2828
field.save()
2929
self.assertIsNotNone(field.id)
30-
self.assertEqual(str(field), "library | book published")
30+
self.assertEqual(str(field), "Library | book published")
3131

3232
def test_metadata(self):
3333
from .models import Book
@@ -188,3 +188,100 @@ def test_relational_conditions(self):
188188
metadata = book2.get_metadata_fieldlist()
189189
fields = {x[1]: x for x in metadata}
190190
self.assertIn("dewey_decimal", fields)
191+
192+
def test_localisation_dependent_formatting(self):
193+
from .models import Book
194+
from django.utils import translation
195+
from django.test import override_settings
196+
197+
field = ExtraField(
198+
content_type=self.book_type,
199+
label="Publication Date",
200+
name="pub_date",
201+
widget="date",
202+
)
203+
field.save()
204+
205+
book = Book(
206+
name="Test Book",
207+
metadata={"pub_date": "2026-02-03"},
208+
)
209+
book.save()
210+
211+
# Set DJANGO_USER_DEFINED_FIELD_DATE_FORMAT to None to enable locale-aware formatting.
212+
# When None, date_format() respects the active locale's DATE_FORMAT setting.
213+
with override_settings(DJANGO_USER_DEFINED_FIELD_DATE_FORMAT=None):
214+
# https://github.com/django/django/blob/main/django/conf/locale/en_AU/formats.py
215+
with translation.override("en-au"):
216+
metadata = book.get_metadata_fieldlist()
217+
fields = {x[1]: x for x in metadata}
218+
self.assertEqual(fields["pub_date"][3], "3 Feb 2026")
219+
220+
# https://github.com/django/django/blob/main/django/conf/locale/en/formats.py
221+
with translation.override("en-us"):
222+
metadata = book.get_metadata_fieldlist()
223+
fields = {x[1]: x for x in metadata}
224+
self.assertEqual(fields["pub_date"][3], "Feb. 3, 2026")
225+
226+
def test_date_formatting(self):
227+
from .models import Book
228+
from django.test import override_settings
229+
230+
field = ExtraField(
231+
content_type=self.book_type,
232+
label="Publication Date",
233+
name="pub_date",
234+
widget="date",
235+
)
236+
field.save()
237+
238+
book = Book(
239+
name="Test Book",
240+
metadata={"pub_date": "2026-02-03"},
241+
)
242+
book.save()
243+
244+
with override_settings(DJANGO_USER_DEFINED_FIELD_DATE_FORMAT="d/m/Y"):
245+
metadata = book.get_metadata_fieldlist()
246+
fields = {x[1]: x for x in metadata}
247+
self.assertEqual(fields["pub_date"][3], "03/02/2026")
248+
249+
with override_settings(DJANGO_USER_DEFINED_FIELD_DATE_FORMAT="Y-m-d"):
250+
metadata = book.get_metadata_fieldlist()
251+
fields = {x[1]: x for x in metadata}
252+
self.assertEqual(fields["pub_date"][3], "2026-02-03")
253+
254+
def test_date_formatting_invalid_date(self):
255+
from .models import Book
256+
257+
field = ExtraField(
258+
content_type=self.book_type,
259+
label="Publication Date",
260+
name="pub_date",
261+
widget="date",
262+
)
263+
field.save()
264+
265+
# book with string date value,
266+
book = Book(
267+
name="Test Book",
268+
metadata={"pub_date": "not-a-valid-date"},
269+
)
270+
book.save()
271+
272+
# Test that invalid date is kept
273+
metadata = book.get_metadata_fieldlist()
274+
fields = {x[1]: x for x in metadata}
275+
self.assertEqual(fields["pub_date"][3], "not-a-valid-date")
276+
277+
# book with int date value
278+
book = Book(
279+
name="Test Book",
280+
metadata={"pub_date": 1234567890},
281+
)
282+
book.save()
283+
284+
# Test that invalid date is kept
285+
metadata = book.get_metadata_fieldlist()
286+
fields = {x[1]: x for x in metadata}
287+
self.assertEqual(fields["pub_date"][3], 1234567890)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "django-user-defined-fields"
3-
version = "0.0.23"
3+
version = "0.0.24"
44
description = "A Django app for user defined fields"
55
authors = ["Aidan Lister <aidan@uptickhq.com>"]
66
license = "MIT"

userdefinedfields/fields.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
from datetime import datetime
12
from functools import partialmethod
23

4+
from django.conf import settings
35
from django.contrib.contenttypes.models import ContentType
46
from django.core.cache import cache
57
from django.core.exceptions import FieldDoesNotExist
68
from django.db.models import JSONField
79
from django.db.models.fields.related import ForeignKey
10+
from django.utils.formats import date_format
811

912
from .models import ExtraField
1013

@@ -23,7 +26,6 @@ def __init__(self, *args, **kwargs):
2326
super().__init__(*args, **kwargs)
2427

2528
def _get_EXTRAFIELD_fieldlist(self, obj, field, use_cache=False):
26-
2729
# grab the relevant extrafields for this content type
2830
# Cache the results, if using the cache
2931
if use_cache:
@@ -100,7 +102,9 @@ def _get_EXTRAFIELD_fieldlist(self, obj, field, use_cache=False):
100102
break
101103

102104
# Check to see whether the condition is satisfied.
103-
if str(getattr(target_obj, f"{dc_field.name}_id")) not in dc.values.split(","):
105+
if str(
106+
getattr(target_obj, f"{dc_field.name}_id")
107+
) not in dc.values.split(","):
104108
# Don't add the field if the id is not on the object
105109
break
106110
else:
@@ -113,6 +117,16 @@ def _get_EXTRAFIELD_fieldlist(self, obj, field, use_cache=False):
113117
for f in filtered_fields:
114118
val = data.get(f.name, None)
115119

120+
if f.widget == "date" and val:
121+
try:
122+
date_obj = datetime.strptime(val, "%Y-%m-%d").date()
123+
date_format_str = getattr(
124+
settings, "DJANGO_USER_DEFINED_FIELD_DATE_FORMAT", "Y-m-d"
125+
)
126+
val = date_format(date_obj, date_format_str)
127+
except (ValueError, TypeError):
128+
pass
129+
116130
# overwrite val with the pretty value if it's a choice field
117131
if "choices" in f.field_settings:
118132
choices = {
@@ -147,11 +161,15 @@ def contribute_to_class(self, cls, name, **kwargs):
147161
setattr(
148162
cls,
149163
f"get_cached_{name}_display",
150-
partialmethod_with_self(self._get_EXTRAFIELD_display, field=self, use_cache=True),
164+
partialmethod_with_self(
165+
self._get_EXTRAFIELD_display, field=self, use_cache=True
166+
),
151167
)
152168
setattr(
153169
cls,
154170
f"get_cached_{name}_fieldlist",
155-
partialmethod_with_self(self._get_EXTRAFIELD_fieldlist, field=self, use_cache=True),
171+
partialmethod_with_self(
172+
self._get_EXTRAFIELD_fieldlist, field=self, use_cache=True
173+
),
156174
)
157175
super().contribute_to_class(cls, name)

0 commit comments

Comments
 (0)