首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有精确M2M集的Django M2M滤波器QuerySet

具有精确M2M集的Django M2M滤波器QuerySet
EN

Stack Overflow用户
提问于 2015-01-29 07:28:37
回答 1查看 275关注 0票数 2

假设我有以下3个模型,其中2个模型中的每个模型都与第三个模型具有M2M关系。

代码语言:javascript
复制
class FirstModel(models.Model):
    third_model = models.ManyToMany('ThirdModel')


class SecondModel(models.Model):
    third_model = models.ManyToMany('ThirdModel')


class ThirdModel(models.Model):
    pass

现在,进一步假设我有一个特定的SecondModel对象和一个FirstModel QuerySet。我需要过滤QuerySet,以便得到的QuerySet只包含FirstModel对象,这些对象使用ThirdModel设置的M2M关系与使用ThirdModel设置的SecondModel对象的M2M关系完全相同。

代码语言:javascript
复制
def some_filtering_method(first_model_qs, second_model):
    third_models_set = second_model.third_model_set.all()
    first_model_ids = list()
    for third_model in third_models_set:
        first_model_ids.append(
            [first_model.pk
             for first_model in third_model.first_model_set.all()])
    intersection_of_first_model_ids = get_intersection(first_model_ids)
    return first_model_qs.filter(pk__in=intersection_of_first_model_ids)

在Django中有没有一种更有Pythonic风格的方法来做到这一点?我尝试了以下方法,但没有成功(在查看原始查询之后,很明显为什么它不能工作)。

代码语言:javascript
复制
import operator

from django.db.models import Q


def some_filtering_method(first_model_qs, second_model):
    return first_model_qs.filter(
        reduce(
            operator.and_, 
            (Q(third_model_set__contains=x) 
             for x in second_model.third_model_set.all())
        )
    )
EN

回答 1

Stack Overflow用户

发布于 2015-01-29 08:47:38

我不确定最具Pythonic风格的方式,但可能最具Djangonic风格的方式是使用custom Manager

在Django1.6及更早版本中,您需要分别设置管理器和QuerySet:

代码语言:javascript
复制
class SharedM2MSetQuerySet(models.QuerySet):
    def shared(self):
        pass
        # your code here

class SharedM2MSetManager(models.Manager):
    def get_queryset(self):
        return PersonQuerySet(self.model, using=self._db)

    def shared(self,other):
        return self.get_queryset().shared(other)

    class FirstModel(models.Model):
        third_model = models.ManyToMany('ThirdModel')
        manager = SharedM2MSetQuerySet.as_manager()

如果你使用的是Django1.7,你可以通过使用QuerySet as a Manager来简化很多操作,如下所示:

代码语言:javascript
复制
class SharedM2MSetQuerySet(models.Manager):
    def shared(self,other):
        pass
        # your code here

class FirstModel(models.Model):
    third_model = models.ManyToMany('ThirdModel')
    manager = SharedM2MSetQuerySet.as_manager()

class SecondModel(models.Model):
    third_model = models.ManyToMany('ThirdModel')

class ThirdModel(models.Model):
    pass

在这两种情况下,这将允许您执行以下操作:

代码语言:javascript
复制
my_obj = SecondModel.objects.first()
for i in FirstModel.objects.shared(my_obj):
    do_the_thing(i)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28204387

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档