这是我的疑问:
Personne
模型,可以通过PersonneTravel
进行一次或多次旅行。PersonneTravel
中,travel
字段是TagWithValue
s
是一个开始'约会" 1954-05-01" e
是" 1999-05-01" travel
是一个字符串,如" Paris,France" 所以我做了一个基本的"搜索"过滤谁做了旅行和何时。
在这里我是如何做到这一点的,因为我是django的初学者,我非常确定它可以进行优化:
pk
个匹配TagWithValue
的{{1}}个value
pk
PersonneTravel
之前与之前相匹配的旅行Personne
pk之前匹配的所有PersonneTravel
我想只返回一个这样的联接(当然这是不是很好的sql ,但只是为了得到一个好主意):
SELECT ALL PersonneTravel PT
JOIN Personne P on P.personne_travel__pk = PT.pk
JOIN TagWithValue T
WHERE T.personne__pk = P.pk
AND T.value = "Paris, France"
AND T.tag = TYPE_GOOGLEMAPS
有没有办法对此进行优化并使用以下代码执行此操作?
q = Q()
if s:
q = q & Q(date_start__gte=s)
if e:
q = q & Q(date_end__lte=e)
retour = [a[0] for a in TagWithValue.objects.filter(
type_tag__exact=BaseTag.TYPE_GOOGLEMAPS,
value__exact=travel).values_list('pk')]
retour = PersonneTravel.objects.filter(Q(travel__in=retour) & q)\
.values_list('personne__pk')
if len(retour):
retour = Personne.objects.filter(pk__in=retour)
答案 0 :(得分:1)
此处无需使用Q()
。将flat=True
与values_list()
一起使用可获取值列表,而不是值类型列表。可以使用Django模型的ForeignKey
列中的related_name进一步简化此解决方案。
key = {}
if s:
key['date_start__gte'] = s
if e:
key['date_end__lte'] = e
key[travel__type_tag__exact] = BaseTag.TYPE_GOOGLEMAPS
key[travel__value__exact] = travel
retour = PersonneTravel.objects.filter(**key)\
.values_list('personne__pk', flat=True)
if len(retour):
retour = Personne.objects.filter(pk__id__in=retour)
related_name
示例:假设related_personne
分别是Personne
模型中PersonneTravel
的相关名称。
key = {}
key['related_personne__travel__type_tag__exact'] = BaseTag.TYPE_GOOGLEMAPS
key['related_personne__travel__value__exact'] = travel
if s:
key['related_personne__date_start__gte'] = s
if e:
key['related_personne__date_end__lte'] = e
retour = Personne.objects.filter(**key)
答案 1 :(得分:0)
我认为您可以使用django的Q-objects
语法在__
之后执行此操作:
query = Personne.objects.filter(personnetravel__travel__value__exact=travel,
personnetravel__travel__type_tag__exact=BaseTag.TYPE_GOOGLEMAPS)
# because django querysets are lazy you can add the date filters now
if s:
query = query.filter(personnetravel__date_start__gte=s)
if e:
query = query.filter(personnetravel__date_end__lte=e)