Django:相关模型的多个实例上的过滤器()
Django: filter() on multiple instances of related models
我的模型如下:我有一组Dude
,每个Dude
都有一组偏好。我可以根据他们的单一偏好轻松找到 Dude
,但我需要找到那些偏好两种不同事物的人。我试图将两个 Q
对象传递给 filter()
函数,但在生成的 SQL 中,这两个 Q
对象引用相同的相关 Preference
。我希望他们指的是两个不同的 Preferences
。更糟糕的是,我需要查询相关模型的几个属性(=Preference
),所以我不能使用简单的__in
.
型号:
class Dude(models.Model):
name = models.CharField(max_length=200)
class Preference(models.Model):
name = models.CharField(max_length=200)
how_much = models.CharField(max_length=200)
dude = models.ForeignKey(Dude)
测试用例:
class DudesTestCase(TestCase):
def setUp(self):
dude = Dude.objects.create(name = 'Dude')
cheese = Preference.objects.create(name = 'Cheese', how_much = "very", dude = dude)
bacon = Preference.objects.create(name = 'Bacon', how_much = "absolutely_love", dude = dude)
# does work
def test_cheese_lovers(self):
d = Dude.objects.filter(preference__name = 'Cheese', how_much = "very")
self.assertEquals(d[0].name, 'Dude')
# does not work - wants a single Preference to be both cheese and bacon
def test_cheese_and_bacon_lovers(self):
d = Dude.objects.filter(
Q(preference__name = 'Cheese', how_much = "very"),
Q(preference__name = 'Bacon', how_much = "absolutely_love"),
)
self.assertEquals(d[0].name, 'Dude')
澄清:
我不想找喜欢奶酪或培根的人,我需要同时满足这两个条件的人。
为模型添加相关名称:
class Preference(models.Model):
name = models.CharField(max_length=200)
dude = models.ForeignKey(Dude, related_name='preferences')
并使用 IN
和 annotate
:
Dude.objects.filter(preferences__name__in=['Cheese', 'Bacon']) \
.annotate(cnt=Count('preferences__name') \
.filter(cnt=2)
我认为这应该可行
def test_cheese_and_bacon_lovers(self):
d = Dude.objects.filter(
preference__name='Cheese',
how_much__in=("very", "absolutely_love"),
).filter(
preference__name='Bacon',
how_much__in=("very", "absolutely_love"),
)
self.assertEquals(d[0].name, 'Dude')
此用法在此处的文档中进行了描述:
https://docs.djangoproject.com/en/1.8/topics/db/queries/#spanning-multi-valued-relationships
我的模型如下:我有一组Dude
,每个Dude
都有一组偏好。我可以根据他们的单一偏好轻松找到 Dude
,但我需要找到那些偏好两种不同事物的人。我试图将两个 Q
对象传递给 filter()
函数,但在生成的 SQL 中,这两个 Q
对象引用相同的相关 Preference
。我希望他们指的是两个不同的 Preferences
。更糟糕的是,我需要查询相关模型的几个属性(=Preference
),所以我不能使用简单的__in
.
型号:
class Dude(models.Model):
name = models.CharField(max_length=200)
class Preference(models.Model):
name = models.CharField(max_length=200)
how_much = models.CharField(max_length=200)
dude = models.ForeignKey(Dude)
测试用例:
class DudesTestCase(TestCase):
def setUp(self):
dude = Dude.objects.create(name = 'Dude')
cheese = Preference.objects.create(name = 'Cheese', how_much = "very", dude = dude)
bacon = Preference.objects.create(name = 'Bacon', how_much = "absolutely_love", dude = dude)
# does work
def test_cheese_lovers(self):
d = Dude.objects.filter(preference__name = 'Cheese', how_much = "very")
self.assertEquals(d[0].name, 'Dude')
# does not work - wants a single Preference to be both cheese and bacon
def test_cheese_and_bacon_lovers(self):
d = Dude.objects.filter(
Q(preference__name = 'Cheese', how_much = "very"),
Q(preference__name = 'Bacon', how_much = "absolutely_love"),
)
self.assertEquals(d[0].name, 'Dude')
澄清: 我不想找喜欢奶酪或培根的人,我需要同时满足这两个条件的人。
为模型添加相关名称:
class Preference(models.Model):
name = models.CharField(max_length=200)
dude = models.ForeignKey(Dude, related_name='preferences')
并使用 IN
和 annotate
:
Dude.objects.filter(preferences__name__in=['Cheese', 'Bacon']) \
.annotate(cnt=Count('preferences__name') \
.filter(cnt=2)
我认为这应该可行
def test_cheese_and_bacon_lovers(self):
d = Dude.objects.filter(
preference__name='Cheese',
how_much__in=("very", "absolutely_love"),
).filter(
preference__name='Bacon',
how_much__in=("very", "absolutely_love"),
)
self.assertEquals(d[0].name, 'Dude')
此用法在此处的文档中进行了描述:
https://docs.djangoproject.com/en/1.8/topics/db/queries/#spanning-multi-valued-relationships