Django:filter()在相关模型的多个实例上



我的模型如下:我有一组Dudes,每个Dudes都有一组首选项。我可以很容易地根据他们的单一偏好找到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')

澄清:我不想发现男人喜欢奶酪或培根,我需要人们同时满足这两个条件。

我认为这应该能在中工作

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-多值关系

向模型添加相关名称:

class Preference(models.Model):
    name = models.CharField(max_length=200)
    dude = models.ForeignKey(Dude, related_name='preferences')

并使用INannotate:

Dude.objects.filter(preferences__name__in=['Cheese', 'Bacon']) 
  .annotate(cnt=Count('preferences__name') 
  .filter(cnt=2)

最新更新