假设我有以下3个模型,其中2个模型中的每个模型都与第三个模型具有M2M关系。
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关系完全相同。
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风格的方法来做到这一点?我尝试了以下方法,但没有成功(在查看原始查询之后,很明显为什么它不能工作)。
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())
)
)发布于 2015-01-29 08:47:38
我不确定最具Pythonic风格的方式,但可能最具Djangonic风格的方式是使用custom Manager。
在Django1.6及更早版本中,您需要分别设置管理器和QuerySet:
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来简化很多操作,如下所示:
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在这两种情况下,这将允许您执行以下操作:
my_obj = SecondModel.objects.first()
for i in FirstModel.objects.shared(my_obj):
do_the_thing(i)https://stackoverflow.com/questions/28204387
复制相似问题