首页 > 解决方案 > 从 Django 中的 QuerySet 中排除对象实例的最佳方法是什么(在这种情况下 filter() 不是一个选项)?

问题描述

现在我能想到的最好的解决方案是在特定实例上单独使用 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)

标签: pythondjangodjango-modelsdjango-formsdjango-queryset

解决方案


这可能很难。django.db.models.functions.TruncDatewithfunctions.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'))

推荐阅读