覆盖 Django DateField 上的查询以更改搜索的日期
Override query on Django DateField to change date searched for
我在 Django 中有一个代表一周的模型。我想让某人输入任何日期并让模型自动保存一周的开始。很简单,覆盖保存即可。
class Week(models.Model):
start_date = models.DateField()
def save(self):
self.start_date = self.start_date - datetime.timedelta(days=date.weekday())
但我也希望有人能够查询任何一天并获得一周。因此,例如,我希望有人这样做:
this_week = Week.objects.filter(start_date=date.today())
今天是星期三,获取周对象,其中日期设置为一周的开始。它需要适用于任何日期,而不仅仅是今天。
我知道我们可以在管理器中覆盖 get_queryset,但是有没有办法编辑实际搜索的内容?我能找到的每个经理示例都只是以静态方式更改了查询集。或者我最好的选择是尝试子类化 DateField?
(注意上面的代码是输入的,简化的,可能包含错误,但它在我的实际代码中有效)
在数据库级别,您可以根据 start_date 进行排序,而不是默认的 primary_key
class Week(models.Model):
start_date = models.DateField()
class Meta:
ordering = ['start_date']
从这里开始,很容易找到您想要的那一周。
week = Week.objects.filter(start_date__lte=date.today()).first()
使用 Meta
的替代方法是在查询中简单地使用 order_by
。
week = Week.objects.filter(start_date__lte=date.today()).order_by('start_date').first()
我们可以将 DateField
子类化为每次将日期时间清理到一周的开始。因此看起来像:
from django.db.models.fields import DateField
from datetime import timedelta
class <strong>WeekField</strong>(DateField):
def <strong>to_python</strong>(self, value):
value = super().to_python(value)
if value is not None:
value -= timedelta(days=value.weekday())
return value
然后我们可以使用WeekField
创建、过滤等。例如,我们可以在 Week
模型中指定:
class Week(models.Model):
week = <strong>WeekField()</strong>
然后例如使用 .get_or_create(…)
:
>>> from datetime import date
>>> Week.objects.get_or_create(week=date.today())
(<Week: Week object (1)>, True)
>>> Week.objects.get_or_create(week=date.today())
(<Week: Week object (1)>, False)
按周过滤:
>>> Week.objects.filter(week=date(2021, 8, 31))
<QuerySet [<Week: Week object (1)>]>
>>> Week.objects.filter(week=date(2021, 8, 2))
<QuerySet []>
查看一周的开始 .values()
:
>>> Week.objects.values()
<QuerySet [{'id': 1, 'week': datetime.date(2021, 8, 30)}]>
我没有对此进行广泛测试,但我想大部分功能都已涵盖。如果还有未涵盖的用例,请 ping 我。
我在 Django 中有一个代表一周的模型。我想让某人输入任何日期并让模型自动保存一周的开始。很简单,覆盖保存即可。
class Week(models.Model):
start_date = models.DateField()
def save(self):
self.start_date = self.start_date - datetime.timedelta(days=date.weekday())
但我也希望有人能够查询任何一天并获得一周。因此,例如,我希望有人这样做:
this_week = Week.objects.filter(start_date=date.today())
今天是星期三,获取周对象,其中日期设置为一周的开始。它需要适用于任何日期,而不仅仅是今天。
我知道我们可以在管理器中覆盖 get_queryset,但是有没有办法编辑实际搜索的内容?我能找到的每个经理示例都只是以静态方式更改了查询集。或者我最好的选择是尝试子类化 DateField?
(注意上面的代码是输入的,简化的,可能包含错误,但它在我的实际代码中有效)
在数据库级别,您可以根据 start_date 进行排序,而不是默认的 primary_key
class Week(models.Model):
start_date = models.DateField()
class Meta:
ordering = ['start_date']
从这里开始,很容易找到您想要的那一周。
week = Week.objects.filter(start_date__lte=date.today()).first()
使用 Meta
的替代方法是在查询中简单地使用 order_by
。
week = Week.objects.filter(start_date__lte=date.today()).order_by('start_date').first()
我们可以将 DateField
子类化为每次将日期时间清理到一周的开始。因此看起来像:
from django.db.models.fields import DateField
from datetime import timedelta
class <strong>WeekField</strong>(DateField):
def <strong>to_python</strong>(self, value):
value = super().to_python(value)
if value is not None:
value -= timedelta(days=value.weekday())
return value
然后我们可以使用WeekField
创建、过滤等。例如,我们可以在 Week
模型中指定:
class Week(models.Model):
week = <strong>WeekField()</strong>
然后例如使用 .get_or_create(…)
:
>>> from datetime import date
>>> Week.objects.get_or_create(week=date.today())
(<Week: Week object (1)>, True)
>>> Week.objects.get_or_create(week=date.today())
(<Week: Week object (1)>, False)
按周过滤:
>>> Week.objects.filter(week=date(2021, 8, 31))
<QuerySet [<Week: Week object (1)>]>
>>> Week.objects.filter(week=date(2021, 8, 2))
<QuerySet []>
查看一周的开始 .values()
:
>>> Week.objects.values()
<QuerySet [{'id': 1, 'week': datetime.date(2021, 8, 30)}]>
我没有对此进行广泛测试,但我想大部分功能都已涵盖。如果还有未涵盖的用例,请 ping 我。