#34962: Support for overriding result of model field values
-------------------------------------+-------------------------------------
Reporter: | Owner: nobody
piraka9011 |
Type: New | Status: new
feature |
Component: Database | Version: 4.2
layer (models, ORM) |
Severity: Normal | Keywords: QuerySet.extra
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
We have many models with timestamp fields (ex. `created_at`, `updated_at`,
etc.) that store `DateTimeField`s.
We use Django as a REST API for web and mobile clients written using
JavaScript where time is stored as milliseconds since the UNIX epoch (i.e.
`Date.now()`).
To minimize the amount of processing we do client side, we convert
`DateTimeField`s to milliseconds using a Django Rest Framework (DRF)
serializer that looks like this:
{{{
class TimestampDateTimeField(serializers.DateTimeField):
"""Convert Python datetime to/from Unix timestamp in milliseconds.
For use with JavaScript's Date objects which use ms since epoch, not
seconds.
"""
def to_representation(self, value):
return round(value.timestamp() * 1000)
def to_internal_value(self, value):
try:
result = datetime.fromtimestamp(value / 1000,
timezone.get_default_timezone())
return super(TimestampDateTimeField,
self).to_internal_value(result)
except TypeError:
raise serializers.ValidationError("Datetime must be a number,
not a string")
}}}
Ideally, we could instead do this data manipulation at the database layer
using the `Extract` function **but** with the same behavior as the
serializer where we can override the original name of the field.
Example:
{{{
# This will currently throw an error
# ValueError: The annotation 'updated_at' conflicts with a field on the
model.
m = MyModel.objects.filter(user=user).annotate(
updated_at=Extract("updated_at", "epoch") * 1000
)
}}}
The way we can do this instead is using the `extra()` method from the
`QuerySet` API to generate a query that would look like:
{{{
SELECT (EXTRACT(EPOCH FROM app_mymodel.updated_at) * 1000) AS updated_at
FROM app_mymodel
WHERE app_mymodel.user_id = 42
LIMIT 1;
}}}
I did my best to look online and in the docs for potential
solutions/workarounds, but all point back to using the `extra()`. Is there
a way to do this w/o using `extra()`?
--
Ticket URL: <https://code.djangoproject.com/ticket/34962>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018bb462c080-3800d54d-4e94-4755-9472-22de32148916-000000%40eu-central-1.amazonses.com.