从 Django 中的 QuerySet 中排除对象实例的最佳方法是什么(在这种情况下,filter() 不是一个选项)?
What is the best way to exclude object instances from a QuerySet in Django (filter() not an option in this case)?
目前我能想到的最佳解决方案是在特定实例上单独使用 queryset.exclude(pk=instance.pk)。
场景是我需要为几个字段过滤模型查询集,然后还要检查日期字段是否与给定值匹配。通常我只会过滤 date=mydate 但在我的情况下我需要首先使用不同模型中存储的时区计算日期(这就是为什么我不能简单地使用过滤器)
现在我的代码(有效但似乎是一种 hack-y 过滤方式)看起来像这样:
user_tracks = HabitTrack.objects.filter(user=user)
filtered_user_tracks = user_tracks
for t in user_tracks:
if not HabitEvent.objects.filter(user=user, track=t, date_expected=t.get_timezone_corrected_datetime_now().date(), post__isnull=True).exists():
print("Excluding ", t.track_name, " with track specific time of ", t.get_timezone_corrected_datetime_now(), "from the list of options")
filtered_user_tracks = filtered_user_tracks.exclude(pk=t.pk)
else:
print("Including ", t.track_name, " with track specific time of ", t.get_timezone_corrected_datetime_now(), "in the list of options")
对于上下文,这是我的 ModelForm 中的一个片段,因此我可以将表单选择限制为仅对用户“今天”可用的选项,其中“今天”是根据用户的时区计算的。
(这也是我第一次在SO上提问,所以如果需要澄清我会尽力清理我的问题,谢谢!)
在 HabitTrack 模型中:
def get_timezone_corrected_datetime_now(self):
return datetime.now(self.timezone)
这可能很难。 django.db.models.functions.TruncDate
和 functions.Now
可能有效,但我不知道是否可以使用 F
实例更改时区。如果您知道用户的足迹都在同一个时区,这会让事情变得更容易。否则,对于短期而言,您可能必须非规范化 HabitEvent.date_expected
以便您拥有完整的日期时间和本地化日期。
编辑:
更好的答案
您还可以使用数据库的函数创建自己的 Func 实例。如果您使用的是 postgres,timezone(zone, timestamp)
(docs 9.9.3) 可能会满足您的需求。
您的函数可能如下所示:
class LocalizedNow(Func):
function = 'timezone'
template = '%(function)s(%(expressions)s, NOW())'
然后您可以在查询中使用它:
HabitEvent.objects.filter(expected_date=LocalizedNow('track__timezone'))
目前我能想到的最佳解决方案是在特定实例上单独使用 queryset.exclude(pk=instance.pk)。
场景是我需要为几个字段过滤模型查询集,然后还要检查日期字段是否与给定值匹配。通常我只会过滤 date=mydate 但在我的情况下我需要首先使用不同模型中存储的时区计算日期(这就是为什么我不能简单地使用过滤器)
现在我的代码(有效但似乎是一种 hack-y 过滤方式)看起来像这样:
user_tracks = HabitTrack.objects.filter(user=user)
filtered_user_tracks = user_tracks
for t in user_tracks:
if not HabitEvent.objects.filter(user=user, track=t, date_expected=t.get_timezone_corrected_datetime_now().date(), post__isnull=True).exists():
print("Excluding ", t.track_name, " with track specific time of ", t.get_timezone_corrected_datetime_now(), "from the list of options")
filtered_user_tracks = filtered_user_tracks.exclude(pk=t.pk)
else:
print("Including ", t.track_name, " with track specific time of ", t.get_timezone_corrected_datetime_now(), "in the list of options")
对于上下文,这是我的 ModelForm 中的一个片段,因此我可以将表单选择限制为仅对用户“今天”可用的选项,其中“今天”是根据用户的时区计算的。
(这也是我第一次在SO上提问,所以如果需要澄清我会尽力清理我的问题,谢谢!)
在 HabitTrack 模型中:
def get_timezone_corrected_datetime_now(self):
return datetime.now(self.timezone)
这可能很难。 django.db.models.functions.TruncDate
和 functions.Now
可能有效,但我不知道是否可以使用 F
实例更改时区。如果您知道用户的足迹都在同一个时区,这会让事情变得更容易。否则,对于短期而言,您可能必须非规范化 HabitEvent.date_expected
以便您拥有完整的日期时间和本地化日期。
编辑:
更好的答案
您还可以使用数据库的函数创建自己的 Func 实例。如果您使用的是 postgres,timezone(zone, timestamp)
(docs 9.9.3) 可能会满足您的需求。
您的函数可能如下所示:
class LocalizedNow(Func):
function = 'timezone'
template = '%(function)s(%(expressions)s, NOW())'
然后您可以在查询中使用它:
HabitEvent.objects.filter(expected_date=LocalizedNow('track__timezone'))