繁体   English   中英

Django ORM:筛选外键属性的元组

[英]Django ORM: filter for tuples of foreign key attributes

我正在编写一项匹配服务,该服务将根据重叠的专业知识为您提供配置文件。 例如,如果您需要python专业知识,它将与您提供python专业知识的人士相匹配。

我在确定如何使用Django ORM构造查询时遇到麻烦。

设定

我有模特:

class Profile(models.Model):
    pass

class Expertise(models.Model):
    profile = db.ForeignKey('profile', on_delete=models.CASCADE)
    name = db.CharField(choices=[(1, 'python'), (2, 'javascript'), (3, 'golang')], max_length =255)
    direction = db.CharField(choices=[('offered', 'offered'), ('requested', 'requested')], max_length = 255)

数据

我得到的数据基本上如下所示:

# setup some fields
profile = Profile()
profile.save()

Expertise(profile=profile, name=1, direction='requested').save()
Expertise(profile=profile, name=2, direction='offered').save()

明显错误的尝试

Profile.objects.filter(
   expertise__name__in = [e.name for e in profile.expertise_set()]
   expertise__direction__in = [e.direction for e in profile.expertise_set()]
)

我本质上是在寻找在查询中组合布尔AND和布尔OR的能力。

我会用另一种技术...

在SQL中,我将按照以下方式进行操作:

SELECT * FROM app_profiles JOIN app_expertise on app_profiles.id = app_expertise.app_profiles_id 
WHERE 
   (app_expertise.direction = 'offered' AND app_expertise.name = 1) OR
   (app_expertise.direction = 'requested' AND app_expertise.name = 2)

预期行为

>>> maus = Profile.objects.get_or_create(name='Maus')[0]
>>> kungphu = Profile.objects.get_or_create(name='kungphu')[0]
>>> strange = Profile.objects.get_or_create(name='Dr. Strange')[0]
>>> thanos = Profile.objects.get_or_create(name='thanos')[0]
>>> 
>>> # maus offers golang and requests python
>>> Expertise.objects.get_or_create(
...     profile=maus, 
...     name=Expertise.NAME_PYTHON, 
...     direction=Expertise.DIRECTION_REQUESTED,
... )[0]
<Expertise: Python (Requested by Maus)>
>>> Expertise.objects.get_or_create(
...     profile=maus, 
...     name=Expertise.NAME_GOLANG, 
...     direction=Expertise.DIRECTION_OFFERED,
... )[0]
<Expertise: Golang (Offered by Maus)>
>>> # kungphu offers python and requests golang, they will match 
>>> # with mous both because of golang and python compatibility
>>> Expertise.objects.get_or_create(
...     profile=kungphu, 
...     name=Expertise.NAME_PYTHON, 
...     direction=Expertise.DIRECTION_OFFERED,
... )[0]
<Expertise: Python (Requested by kungphu)>
>>> Expertise.objects.get_or_create(
...     profile=kungphu, 
...     name=Expertise.NAME_GOLANG, 
...     direction=Expertise.DIRECTION_REQUESTED,
... )[0]
<Expertise:Golang (Requested by kungphu)>
>>> # Doctor Strange is trying to learn golang, he will match with maus as 
>>> # a result.
>>> Expertise.objects.get_or_create(
...     profile=kungphu, 
...     name=Expertise.NAME_GOLANG, 
...     direction=Expertise.DIRECTION_REQUESTED,
... )[0]
<Expertise:Golang (Requested by strange)>
>>> 
>>> # Thanos both offers and requests Python, because balance, I guess.
>>> Expertise.objects.get_or_create(
...     profile=thanos, 
...     name=Expertise.NAME_PYTHON, 
...     direction=Expertise.DIRECTION_REQUESTED,
... )[0]
<Expertise: Python (Requested by thanos)>
>>> Expertise.objects.get_or_create(
...     profile=thanos, 
...     name=Expertise.NAME_PYTHON, 
...     direction=Expertise.DIRECTION_OFFERED,
... )[0]
<Expertise: Python (Offered by thanos)>
>>> 
>>> # maus has requested Python, thanos and kungphu have offered it
>>> # maus has offered golang, dr. strange and kungphu have requested it.
>>> maus.find_matches()
[<Profile: kungphu>, <Profile: thanos>, <Profile: strange>]

对于复杂的查询,Django提供了Q对象

因此,您可以使用以下Q对象查询该表:

Expertise.objects.select_related('profile').filter(
    (Q(direction='offered') & Q(name=1)) | (Q(direction='requested') & Q(name=2))
)

| OR ,而&是自我解释。 你也可以做~QNOT样式的查询。

select_related ,如果您还没有碰到它的话,可以对相关对象进行更有效的查询。 您可以在此处了解更多信息。 https://medium.com/@lucasmagnum/djangotip-select-prefetch-related-e76b683aa457

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM