Django ORM:自定义ListView,并向其查询集添加更多信息

时间:2016-04-25 08:32:06

标签: python django django-orm

我可以列出某个模型(让我们称之为class A),如下所示:

class BaseListView(ListView, MultipleObjectMixin):
    http_method_names = ['get']
    order_field = None

    def get_paginate_by(self, queryset):
        session_manager = SessionManager(self.request.session)
        return session_manager.paginate_by.get()

    def get_context_data(self, **kwargs):
        context = super(BaseListView, self).get_context_data(**kwargs)

        session_manager = SessionManager(self.request.session)
        session_manager.paginate_by.set_to(context)

        return context

到目前为止,这种观点确实需要。现在我必须将它检索的对象列表与另一个对象列表(class B)进行比较。

班级AB的对象都有一个主键及其名称。

我想检查class A中的任何对象是否与name中的任何对象具有相同的class B(主键)。如果A中有B的实例,我想添加某个参数或类似is_in_B=True的内容。

我需要这个,以便我可以在模板中以不同的方式表示A的这些实例。

我怎么能这样做?

这就是我现在想出的:

class AListView(BaseListView):
    model = "A"

    def get_queryset(self):
        queryset = super(AListView, self). get_query_set()

        all_objects_A = A.objects.all()
        all_objects_B = B.objects.all()

        # modify queryset to indicate which instances of A are present in B
        # No idea how to do this

        return queryset

我不确定这是一种合适的做法。

另外,我应该如何修改我的类返回的queryset,以便我可以指出class A的哪些实例与{name的任何实例共享class B 1}}?

1 个答案:

答案 0 :(得分:1)

You can annotate your queryset with a conditional expression to achieve this:

from django.db.models import Case, When, Value

def get_queryset(self):
    # This gives you the queryset of A objects
    queryset = super(AListView, self).get_queryset()
    # List of primary keys of B objects
    all_objects_B = B.objects.all().values_list('pk',flat=True)

    # modify queryset to indicate which instances of A are present in B
    return queryset.annotate(
        is_in_b=Case(When(pk__in=all_objects_B, then=Value(True)),
                       default=Value(False))
        )
    )

Your queryset objects will now have an is_in_b property.

This will work fine if your list of B objects is small. If it is large then I am not sure it is very efficient, and you may need to develop this further to see whether the check (is A in B) can be done directly in the database (possibly requiring raw SQL).