|
11 | 11 | from django.db import models |
12 | 12 | from django.db.models.fields.files import FieldFile |
13 | 13 | from django.forms import model_to_dict |
| 14 | +from django.utils.functional import Promise |
14 | 15 |
|
15 | 16 |
|
16 | 17 | def arbitrary_value_to_basic_type(value: typing.Any) -> str | int | float | bool | None: |
17 | 18 | """Convert an arbitrary value to a basic type that can be JSON serialized.""" |
18 | | - if isinstance(value, (int, float, bool)): |
| 19 | + if isinstance(value, Promise): |
| 20 | + return str(value) |
| 21 | + elif isinstance(value, (int, float, bool)): |
19 | 22 | return value |
20 | 23 | elif isinstance(value, str): |
21 | 24 | return value |
@@ -62,17 +65,21 @@ def _model_to_jsonable_dict( # noqa: C901 |
62 | 65 | jsonable_model_dict: dict[str, str | int | float | bool | None] = { |
63 | 66 | "id": str(instance.pk) if isinstance(instance.pk, uuid.UUID) else instance.pk, |
64 | 67 | "pk": str(instance.pk) if isinstance(instance.pk, uuid.UUID) else instance.pk, |
65 | | - "_meta": types.SimpleNamespace( |
66 | | - app_label=instance._meta.app_label, |
67 | | - model_name=instance._meta.model_name, |
68 | | - verbose_name=instance._meta.verbose_name, |
69 | | - verbose_name_plural=instance._meta.verbose_name_plural, |
70 | | - ), |
| 68 | + "_meta": { |
| 69 | + "app_label": instance._meta.app_label, |
| 70 | + "model_name": str(instance._meta.model_name), |
| 71 | + "verbose_name": str(instance._meta.verbose_name), |
| 72 | + "verbose_name_plural": str(instance._meta.verbose_name_plural), |
| 73 | + }, |
71 | 74 | } |
72 | 75 |
|
73 | 76 | for field, value in model_dict.items(): |
74 | 77 | if isinstance(value, (datetime.datetime, datetime.date, datetime.time)): |
75 | 78 | jsonable_model_dict[field] = value.isoformat() |
| 79 | + elif isinstance(value, Promise): |
| 80 | + # Django's translation system returns a Promise object for translated strings. |
| 81 | + # We can safely convert it to a string. |
| 82 | + jsonable_model_dict[field] = str(value) |
76 | 83 | elif isinstance(value, (uuid.UUID, int, str)): |
77 | 84 | # Is this field just a UUID | int | str, or is it a ForeignKey/OneToOneField? |
78 | 85 | # django.forms.model_to_dict will return a UUID for Proxy model fields, |
@@ -197,6 +204,9 @@ def apply_diff_to_jsonized_models( |
197 | 204 | ) |
198 | 205 |
|
199 | 206 | for field_name, new_value in diff_data.items(): |
| 207 | + if field_name.startswith("_"): |
| 208 | + # Skip private fields |
| 209 | + continue |
200 | 210 | updated_models[model_identifier][field_name] = new_value |
201 | 211 |
|
202 | 212 | return updated_models |
|
0 commit comments