Django通过一个选择器函数获取FK
Django get FK through a selector function
我有 3 个模型:
class A:
start_date=DateField
end_date=DateField
...
@property
def is_valid():
if self.start_date is not None and self.end_date is not None:
return self.start_date <= get_now().date() <= self.end_date
elif (self.start_date is None or self.start_date <= get_now.date()) and self.end_date is None:
return True
class B:
a = ManyToMany(A)
class C:
b = ForeignKey(B)
和一个选择器函数 get_valid_a's
returns 给定单个 class B
class A
的所有有效实例
选择器函数:
def get_valid_a's(B):
return B.A.filter((
Q(start_date__lte=get_now().date()) &
Q(end_date__gte=get_now().date())) | (
Q(start_date__lte=get_now().date()) &
Q(end_date__isnull=True)) | (
Q(start_date__isnull=True) & Q(end_date__isnull=True))
)
我正在寻找这样的东西:
C_with_valid_A = C.objects.filter(
d_pk=d_pk,
b__a__isnull=False,
<here I am lookig to do something like: b__a__in=get_valid_a's(b=b)
)
如有任何帮助,我们将不胜感激!
我会向 A 添加一个 custom manager 并向该管理器添加一个方法,该方法按有效结果进行过滤。你总是可以把它作为一个快速获胜的类方法
(我刚刚粘贴了查询,因为 verify/parse 几乎不可能:D)
class A:
@classmethod
def get_valid(cls):
return cls.objects.filter((
Q(start_date__lte=get_now().date()) & Q(end_date__gte=get_now().date())) | (
Q(start_date__lte=get_now().date()) &
Q(end_date__isnull=True)) | (
Q(start_date__isnull=True) & Q(end_date__isnull=True)))
然后您可以在其他查询中使用此方法
C_with_valid_A = C.objects.filter(
d_pk=d_pk,
b__a__in=A.get_valid()
)
我阅读了一些 Django 文档并发现了一个非常有用的数据库级函数,可以在这种情况下使用 - Exists
抓取查询如下所示
C_with_valid_A = C.objects.annotate(
has_valid_As=Exists(
A.objects.filter((
Q(start_date__lte=get_now().date()) &
Q(end_date__gte=get_now().date())) | (
Q(start_date__lte=get_now().date()) &
Q(end_date__isnull=True)) | (
Q(start_date__isnull=True) & Q(end_date__isnull=True)),
Bs=OuterRef('b')
)).filter(has_valid_As=True,d=d_pk)
对于 Django >= 3.0,相同的查询可以写成
C_with_valid_A = C.objects.filter(
Exists(
A.objects.filter((
Q(start_date__lte=get_now().date()) &
Q(end_date__gte=get_now().date())) | (
Q(start_date__lte=get_now().date()) &
Q(end_date__isnull=True)) | (
Q(start_date__isnull=True) & Q(end_date__isnull=True)),
Bs=OuterRef('b'),
d=d_pk
))
这基本上与下面的第一个查询相同。在我的理解中,OuterRef
表示模型C与模型B之间的关系。
我有 3 个模型:
class A:
start_date=DateField
end_date=DateField
...
@property
def is_valid():
if self.start_date is not None and self.end_date is not None:
return self.start_date <= get_now().date() <= self.end_date
elif (self.start_date is None or self.start_date <= get_now.date()) and self.end_date is None:
return True
class B:
a = ManyToMany(A)
class C:
b = ForeignKey(B)
和一个选择器函数 get_valid_a's
returns 给定单个 class B
class A
的所有有效实例
选择器函数:
def get_valid_a's(B):
return B.A.filter((
Q(start_date__lte=get_now().date()) &
Q(end_date__gte=get_now().date())) | (
Q(start_date__lte=get_now().date()) &
Q(end_date__isnull=True)) | (
Q(start_date__isnull=True) & Q(end_date__isnull=True))
)
我正在寻找这样的东西:
C_with_valid_A = C.objects.filter(
d_pk=d_pk,
b__a__isnull=False,
<here I am lookig to do something like: b__a__in=get_valid_a's(b=b)
)
如有任何帮助,我们将不胜感激!
我会向 A 添加一个 custom manager 并向该管理器添加一个方法,该方法按有效结果进行过滤。你总是可以把它作为一个快速获胜的类方法
(我刚刚粘贴了查询,因为 verify/parse 几乎不可能:D)
class A:
@classmethod
def get_valid(cls):
return cls.objects.filter((
Q(start_date__lte=get_now().date()) & Q(end_date__gte=get_now().date())) | (
Q(start_date__lte=get_now().date()) &
Q(end_date__isnull=True)) | (
Q(start_date__isnull=True) & Q(end_date__isnull=True)))
然后您可以在其他查询中使用此方法
C_with_valid_A = C.objects.filter(
d_pk=d_pk,
b__a__in=A.get_valid()
)
我阅读了一些 Django 文档并发现了一个非常有用的数据库级函数,可以在这种情况下使用 - Exists
抓取查询如下所示
C_with_valid_A = C.objects.annotate(
has_valid_As=Exists(
A.objects.filter((
Q(start_date__lte=get_now().date()) &
Q(end_date__gte=get_now().date())) | (
Q(start_date__lte=get_now().date()) &
Q(end_date__isnull=True)) | (
Q(start_date__isnull=True) & Q(end_date__isnull=True)),
Bs=OuterRef('b')
)).filter(has_valid_As=True,d=d_pk)
对于 Django >= 3.0,相同的查询可以写成
C_with_valid_A = C.objects.filter(
Exists(
A.objects.filter((
Q(start_date__lte=get_now().date()) &
Q(end_date__gte=get_now().date())) | (
Q(start_date__lte=get_now().date()) &
Q(end_date__isnull=True)) | (
Q(start_date__isnull=True) & Q(end_date__isnull=True)),
Bs=OuterRef('b'),
d=d_pk
))
这基本上与下面的第一个查询相同。在我的理解中,OuterRef
表示模型C与模型B之间的关系。