如何限制django模板端显示的m2m项目?

时间:2015-08-05 23:11:26

标签: django django-templates django-views django-queryset

我在视图中有一个限制m2m字段的查询集。查询似乎正常工作并获得正确的父对象,但是当我遍历模板中的parent.object_set.all时,我看到m2m对象在技术上不包含在初始查询中(或者不应该包含在内),但是现在包括因为它们是父母的孩子m2m object_set的一部分。

试着把它放在一个更通用的例子中......我完全是在做父母和孩子:

class Parent(models.Model):
    name = models.CharField(max_length=42)
    children = models.ManyToManyField(Child)

class Child(models.Model):
    ...
    # no, I'm not serious on this as a data structure, but for the example....
    male = models.BooleanField()
    female = models.BooleanField()

class ParentListView(ListView):
    ...
    def get_queryset(self):
        ...
        parents = Parent.objects.filter(children__male = True)

在模板中。

{% for parent in parents %}
    {{ parent.name }}
    {% for child in parent.child_set.all %}
        {% comment %}
            oops, I got all the children of this parent....I only want those that were male from the original queryset. I need the child_set to only be those that met the criteria in that first queryset. How do I accomplish this?
        {% endcomment %}
    {% endfor %}
{% endfor %} 

1 个答案:

答案 0 :(得分:1)

您无法使用Django模板语言提供过滤器参数。

在Django 1.7+中,在视图中定义查询集时,可以将prefetch_related与自定义Prefetch对象一起使用。

def get_queryset(self):
    ...
    parents = Parent.objects.filter(
        children__male=True
    ).prefetch_related(
        Prefetch('children', queryset=Child.objects.filter(male=True), to_attr='male_children')
    )

请注意,在上面的示例中,您可能需要使用distinct()来防止每个男孩重复父母。

我们使用了文档中建议的to_attr参数。在模板中,我们然后循环通过男孩。

{% for parent in parents %}
    {{ parent.name }}
    {% for child in parent.male_children %}
        {{ child }}
    {% endfor %}
{% endfor %}