【问题标题】:Django: filter() on multiple instances of related modelsDjango:过滤器()在相关模型的多个实例上
【发布时间】:2015-12-03 13:13:25
【问题描述】:

我的模型如下:我有一组Dudes,每个Dude都有一组偏好。我可以根据他们的单一偏好轻松找到Dudes,但我需要找到那些更喜欢两种不同事物的人。我试图将两个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')

澄清: 我不想找到喜欢奶酪或培根的家伙,我需要同时满足这两个条件的人。

【问题讨论】:

    标签: python django django-models django-orm django-related-manager


    【解决方案1】:

    我认为这应该可行

    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

    【讨论】:

      【解决方案2】:

      为模型添加相关名称:

      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)
      

      【讨论】:

        猜你喜欢
        • 2017-06-22
        • 1970-01-01
        • 2018-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多