【问题标题】:Django: passing a filtered Queryset to a ListView?Django:将过滤后的查询集传递给 ListView?
【发布时间】:2019-01-21 11:16:19
【问题描述】:

使用 Django 基于类的视图,我已经为 Order 对象创建了一个 ListView,并且我创建了一个 FormView 来对这些排序者执行高级搜索。

但是,我不确定如何将过滤后的 FormView 查询集传递给 ListView

这里是代码,带有注释部分来解释问题:

class OrdersListView(PermissionRequiredCanHandleOrders,
                     SelectRelatedMixin, PrefetchRelatedMixin,
                     ModelInContextMixin, SubSectionLastOrders,
                     RestaurantOrdersOnly,
                     ListView):
    model = Order
    paginator_class = DiggPaginator
    paginate_by = 15
    select_related = ('convive__user',)
    prefetch_related = ('orderoperation_set',)
    # will use the template named order_list.html


class OrdersAdvancedSearchView(PermissionRequiredCanHandleOrders,
                               ModelInContextMixin, SubSectionLastOrders,
                               RestaurantOrdersOnly, RestaurantMixin,
                               FormView):
    model = Order
    template_name = "orders/order_advanced_search.html"
    form_class = OrderAdvancedSearchForm


    def form_valid(self, form):

        data = form.cleaned_data
        queryset = Order.objects.all()

        # Here, I'm using the form content to filter the queryset
        # queryset = queryset.filter(some_attribute__in=data['stuff'])

        # MY PAIN POINT IS HERE: what I'm supposed to do here ?
        # my queryset is filtered, and I need to call OrderListView 
        # with it.

        return super().form_valid(form)

【问题讨论】:

  • 使用class class_name(View): 并在其中定义def get(self, request):def post(self, request); 方法。这是在from django.views import View 中定义的,请看这里:docs.djangoproject.com/en/2.1/topics/class-based-views/intro/…
  • @Ahtisham 请问我提供的案例中有一些示例代码吗?请注意,我想保持 OrdersListView 原样。我更改了问题的标题以更明确地说明我的问题。
  • 如果你想要的只是过滤ListView 这听起来像,那么就不需要 POST 表单(POST 通常是修改数据库中的数据)。为什么您的 HTML 页面无法使用搜索参数获取与 URL 中的查询参数相同的 ListView?这样你只需要在你的ListViewget_queryset() 方法中处理GET 参数。

标签: python django django-class-based-views


【解决方案1】:

您应该使用ListView 来过滤带有GET 请求参数的查询集。为此,将表单添加到您的上下文并在获取查询集时对其进行处理:

def get_queryset(self):
    self.form = OrderAdvancedSearchForm(data=self.request.GET or None)
    if self.request.GET and form.is_valid():
        # filter using the form's cleaned_data
        queryset = super().get_queryset().filter(...)
    else:
        queryset = super().get_queryset()
    return queryset

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)  # this calls self.get_queryset() which assigns self.form
    context['form'] = self.form
    return context

现在在您的模板中,您可以只渲染相同的表单,除了它的方法应该是“GET”而不是“POST”。

【讨论】:

  • 注意:由于您使用两种不同的模板,一种用于简单视图,另一种用于“高级”过滤视图,您可以覆盖 get_template_names 方法来选择模板,具体取决于用户选择查看(向 URL 添加查询参数或让两个不同的 URL 指向同一个视图,但向其中一个添加 kwargs 参数)。但是您也可以在一个模板中解决这个问题(使用 javascript 显示/隐藏高级表单)。
  • 感谢@dirkgroten 它帮了很多忙 :)
猜你喜欢
  • 2021-02-07
  • 2021-02-09
  • 2013-10-22
  • 2017-11-25
  • 1970-01-01
  • 2015-03-04
  • 2016-08-06
  • 1970-01-01
  • 2017-07-14
相关资源
最近更新 更多