我该如何在django中过滤多个ForeignKey?

时间:2014-03-19 20:58:44

标签: django join django-queryset

我的non_toxic_items()方法没有返回正确的'组。

目前,

Item.inventory.all() 

返回

Item.inventory.non_toxic_items()

这是我的经理,有问题的方法。请参阅函数中的说明,了解我希望它返回的内容。

#manager.py
from django.db import models


class InventoryManager(models.Manager):

    def get_queryset(self):
        return super(InventoryManager, self).get_queryset().filter(
            shipment__isnull=True, )

    def non_toxic_items(self):
        """
        Return all non-toxic items, not part of a shipment.

        As python code::

    context['my_qs'] = []
    for batch in self.object_list:
        flag = False
        for input in batch.input_set.all():
            if input.material.type.is_toxic:
                flag=True
        if not flag:
            for item in batch.item_set.all():
                if item.shipment is None:
                    context['my_qs'].append(item)
        """
        return super(InventoryManager, self).get_queryset().filter(
            # BUG -- Does not return the same queryset as above python code.
            shipment__isnull=True,
            batch__input__material__type__is_toxic=False).distinct()

这些是模型

from django.db import models
from .managers import InventoryManager
from shipment.models import Shipment


class MaterialType(models.Model):
    type = models.CharField(max_length=255, )
    is_toxic = models.BooleanField(default=False, )
    ...


class Material(models.Model):
    type = models.ForeignKey(MaterialType)
    lot_number = models.CharField(max_length=50, )
    ...


class Batch(models.Model):
    batch_number = models.IntegerField(primary_key=True, )
    ...


class Input(models.Model):
    """
    These are input materials to a batch.
    A batch may contain at most 1 toxic material.
    """
    batch = models.ForeignKey(Batch)
    material = models.ForeignKey(Material)
    ...


class Item(models.Model):
    id_number = models.IntegerField(primary_key=True, )
    batch = models.ForeignKey(Batch, )
    shipment = models.ForeignKey(Shipment, blank=True, null=True, )
    ...
    objects = models.Manager()
    inventory = InventoryManager()

我删除了与查询无关的所有字段。该方法有效,但输出不正确...(它与描述中的代码不匹配)

如果有人比那个昂贵的加入有更好的解决方案,我很乐意听到它。

编辑:更多详情:

# imports go here

class BatchListView(generic.ListView):
    model = Batch
    paginate_by = 25

    def get_context_data(self, **kwargs):
        context = super(BatchListView, self).get_context_data(**kwargs)
        context['items_non_toxic'] = Item.inventory.non_toxic_items()
        context['my_qs'] = []
        for batch in self.object_list:
            flag = False
            for my_input in batch.input_set.all():
                if my_input.material.type.is_toxic:
                    flag=True
            if not flag:
                for my_item in batch.item_set.all():
                    if my_item.shipment is None:
                        context['my_qs'].append(my_item)
        return context

{{my_qs}}#返回73项

,20,21,22,23,24,25,26,27,28,29,30,31,32,14035,14042,14043,14044,14045,14046,14047,14048,14049,14050, 14051,14052,14053,14054,14055,14056,14057,14058,14059,14060,14061,14062,14063,14064,14065,14066,14067,14068,14069,14070,14071,14072,14073,14074,14075, 14076,14077,14078,14079,14080,14081,14082,14083,14084,14085,14086,14087,14088,14089,14090,14091,14092,14093,14094,14095,14096,14097,14098,14099,14100, ,

{{items_non_toxic}}#返回115项

4,5,6,7,8,9,10,11,20,21,22,23,24,25,26,27,28,29,30,31,32,10000,10001,10002 ,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,10020,10021,10022,10023,14035,14042,14043,14044 ,14045,14046,14047,14048,14049,14050,14051,14052,14053,14054,14055,14056,14057,14058,14059,14060,14061,14062,14063,14064,14065,14066,14067,14068,14069 ,14070,14071,14072,14073,14074,14075,14076,14077,14078,14079,14080,14081,14082,14083,14084,14085,14086,14087,14088,14089,14090,14091,14092, 14093,14094,14095,14096,14097,14098,14099,14100,45361,45362,45363,45364,43656,45366,45367,45368,45369,45370,

1 个答案:

答案 0 :(得分:0)

这个解决方案来自twigbog:

http://www.reddit.com/r/django/comments/20v1qi/stackoverflow_how_can_i_filter_across_multiple/cg7db8l

def non_toxic_items(self):
    return super(InventoryManager, self).get_queryset().filter(
        shipment__isnull=True,
        ).exclude(batch__in=Batch.objects.filter(
                input__material__type__is_toxic=True))

https://docs.djangoproject.com/en/1.6/ref/models/querysets/#in描述了所有感兴趣的人在幕后发生的事情。