Created
March 11, 2018 07:20
-
-
Save Azarakhsh/c34a5090d5fae62550d2a95ae0e92da9 to your computer and use it in GitHub Desktop.
Extends dlango_jalali to supports database Extract functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Adding support for Extracting date components for Jalali Date models | |
from django_jalali.db.models import jDateField, jDateTimeField | |
from django.db.models import ( | |
DateField, IntegerField, | |
Transform, | |
) | |
from django.db.models.functions.datetime import TimezoneMixin | |
class jExtract(TimezoneMixin, Transform): | |
lookup_name = None | |
output_field = IntegerField() | |
def __init__(self, expression, lookup_name=None, tzinfo=None, **extra): | |
if self.lookup_name is None: | |
self.lookup_name = lookup_name | |
if self.lookup_name is None: | |
raise ValueError('lookup_name must be provided') | |
self.tzinfo = tzinfo | |
super().__init__(expression, **extra) | |
def as_sql(self, compiler, connection): | |
sql, params = compiler.compile(self.lhs) | |
lhs_output_field = self.lhs.output_field | |
if isinstance(lhs_output_field, jDateTimeField): | |
tzname = self.get_tzname() | |
sql = connection.ops.datetime_extract_sql(self.lookup_name, sql, tzname) | |
elif isinstance(lhs_output_field, jDateField): | |
sql = connection.ops.date_extract_sql(self.lookup_name, sql) | |
else: | |
# resolve_expression has already validated the output_field so this | |
# assert should never be hit. | |
assert False, "Tried to jExtract from an invalid type." | |
return sql, params | |
def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False): | |
copy = super().resolve_expression(query, allow_joins, reuse, summarize, for_save) | |
field = copy.lhs.output_field | |
if not isinstance(field, (jDateField, jDateTimeField)): | |
raise ValueError( | |
'jExtract input expression must be jDateField, jDateTimeField.' | |
) | |
# Passing dates to functions expecting datetimes is most likely a mistake. | |
if type(field) == jDateField and copy.lookup_name in ('hour', 'minute', 'second'): | |
raise ValueError( | |
"Cannot extract time component '%s' from jDateField '%s'. " % (copy.lookup_name, field.name) | |
) | |
return copy | |
class jExtractYear(jExtract): | |
lookup_name = 'year' | |
class jExtractMonth(jExtract): | |
lookup_name = 'month' | |
class jExtractDay(jExtract): | |
lookup_name = 'day' | |
class jExtractWeek(jExtract): | |
""" | |
Return 1-52 or 53, based on ISO-8601, i.e., Monday is the first of the | |
week. | |
""" | |
lookup_name = 'week' | |
class jExtractWeekDay(jExtract): | |
""" | |
Return Sunday=1 through Saturday=7. | |
To replicate this in Python: (mydatetime.isoweekday() % 7) + 1 | |
""" | |
lookup_name = 'week_day' | |
class jExtractQuarter(jExtract): | |
lookup_name = 'quarter' | |
DateField.register_lookup(jExtractYear) | |
DateField.register_lookup(jExtractMonth) | |
DateField.register_lookup(jExtractDay) | |
DateField.register_lookup(jExtractWeekDay) | |
DateField.register_lookup(jExtractWeek) | |
DateField.register_lookup(jExtractQuarter) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment