【问题标题】:Django ListView - Form to filter and sortDjango ListView - 过滤和排序的表单
【发布时间】:2016-01-25 19:47:34
【问题描述】:

我的目标

  • 一个在表格中列出我所有更新(模型)的网站
  • 不要一次显示所有模型(分页 - 每页可能 10 个)
  • 对列表进行过滤和排序

我的想法

  • 我可以使用 ListView 来获取我所有的更新
  • 使用 paginate_by = 10
  • 在我的 QuerySet 中使用表单设置 order_by 或过滤器

我的问题

我不知道如何添加一个表单来修改我的 QuerySet 过滤器和排序。我的想法是使用额外的过滤器和 order_by 修改 get_queryset 中的查询。

我的观点

class MyView(ListView):
    model = Update
    template_name = "updates/update.html"
    paginate_by = 10

    def get_queryset(self):
        return Update.objects.filter(
            ~Q(state=Update.STATE_REJECTED),
            ~Q(state=Update.STATE_CANCELED),
            ~Q(state=Update.STATE_FINISHED),
        ).order_by(
            'planned_release_date'
        )

我的想法

类似的东西。我知道它不是这样工作的......只是为了说明

class MyView(ListView):
    model = Update
    template_name = "updates/update.html"
    paginate_by = 10

    def post(self, request, *args, **kwargs):
        new_context = Update.objects.filter(
            request.POST.get("filter"),
        ).order_by(
            request.POST.get("sorting"),
        )

    def get_queryset(self):
        return Update.objects.filter(
            ~Q(state=Update.STATE_REJECTED),
            ~Q(state=Update.STATE_CANCELED),
            ~Q(state=Update.STATE_FINISHED),
        ).order_by(
            'planned_release_date'
        )

【问题讨论】:

    标签: django forms sorting listview filter


    【解决方案1】:

    你不需要发帖。在 url 中传递过滤器值和 order_by 例如:

    .../update/list/?filter=filter-val&orderby=order-val

    并在 get_queryset 中获取过滤器和 orderby,如下所示:

    class MyView(ListView):
        model = Update
        template_name = "updates/update.html"
        paginate_by = 10
    
        def get_queryset(self):
            filter_val = self.request.GET.get('filter', 'give-default-value')
            order = self.request.GET.get('orderby', 'give-default-value')
            new_context = Update.objects.filter(
                state=filter_val,
            ).order_by(order)
            return new_context
    
        def get_context_data(self, **kwargs):
            context = super(MyView, self).get_context_data(**kwargs)
            context['filter'] = self.request.GET.get('filter', 'give-default-value')
            context['orderby'] = self.request.GET.get('orderby', 'give-default-value')
            return context
    

    确保为过滤和排序提供适当的默认值

    示例表格(您可以根据需要进行修改):

    <form method="get" action="{% url 'update-list' %}">
        <p>Filter: <input type="text" value={{filter}} name="filter"/></p>
        <p>order_by: <input type="text" value={{orderby}} name="orderby"/></p>
        <p><input type="submit" name="submit" value="submit"/></p>
    </form>
    

    【讨论】:

    • 您好,感谢您的解决方案。除了切换页面时我失去了排序和过滤器之外,它正在工作:-(
    • @Rooterle 我已经编辑了我的答案,请检查。我已经编辑了视图和表单。
    • 好的,谢谢 :-) 在模板中,我必须将参数添加到链接中,然后才能正常工作。
    【解决方案2】:

    我在其他地方发布了这个,但我认为这会增加所选答案。

    我认为您最好通过 get_context_data 执行此操作。手动创建 HTML 表单并使用 GET 检索此数据。下面是我写的一个例子。当您提交表单时,您可以使用获取数据通过上下文数据传回。此示例不是根据您的要求量身定制的,但它应该可以帮助其他用户。

    def get_context_data(self, **kwargs):
        context = super(Search, self).get_context_data(**kwargs)
        filter_set = Gauges.objects.all()
        if self.request.GET.get('gauge_id'):
            gauge_id = self.request.GET.get('gauge_id')
            filter_set = filter_set.filter(gauge_id=gauge_id)
    
        if self.request.GET.get('type'):
            type = self.request.GET.get('type')
            filter_set = filter_set.filter(type=type)
    
        if self.request.GET.get('location'):
            location = self.request.GET.get('location')
            filter_set = filter_set.filter(location=location)
    
        if self.request.GET.get('calibrator'):
            calibrator = self.request.GET.get('calibrator')
            filter_set = filter_set.filter(calibrator=calibrator)
    
        if self.request.GET.get('next_cal_date'):
            next_cal_date = self.request.GET.get('next_cal_date')
            filter_set = filter_set.filter(next_cal_date__lte=next_cal_date)
    
        context['gauges'] = filter_set
        context['title'] = "Gauges "
        context['types'] = Gauge_Types.objects.all()
        context['locations'] = Locations.objects.all()
        context['calibrators'] = Calibrator.objects.all()
        # And so on for more models
        return context
    

    【讨论】:

      【解决方案3】:

      我想知道为什么没有人在这里提到这个很酷的库:django-filterhttps://github.com/carltongibson/django-filter

      您可以定义您的逻辑以非常干净地过滤并获得快速工作的表单等。

      在这里演示:https://stackoverflow.com/a/46492378/953553

      【讨论】:

        【解决方案4】:

        我们就是这样做的,这样您也可以进行验证/类型转换:

        class UnitList(PermissionRequiredMixin, ListView):
            """ Class based view to show a list of all buildings for a specific user """
        
            model = Unit
            ordering = ['building', 'unit']
            paginate_by = 100
        
            # Access
            permission_required = ['core.manager_perm']
            raise_exception = True  # If true, give access denied message rather than redirecting to login
        
            def get_queryset(self):
                try:
                    units = self.model.objects.filter(building__company=self.request.user.profile.company)
                except Profile.DoesNotExist:
                    units = self.model.objects.none()
        
                form = UnitSearchForm(self.request.GET)
        
                if form.is_valid():
                    filters = {}
        
                    address = form.cleaned_data['address']
                    neighborhood = form.cleaned_data['neighborhood']
                    beds = form.cleaned_data['beds']
                    amenity = form.cleaned_data['amenity']
        
                    if address:
                        filters['building__street_index__istartswith'] = compute_street_address_index(address)
        
                    if neighborhood:
                        filters['building__neighborhood__icontains'] = neighborhood
        
                    if beds:
                        filters['beds'] = beds
        
                    if amenity:
                        filters['unit_amenities__name__iexact'] = amenity
            
                    units = units.filter(**filters)
        
                return units.select_related('building').order_by(*self.ordering)
        
            def get_context_data(self, **kwargs):
                context = super().get_context_data(**kwargs)
                context['form'] = UnitSearchForm(self.request.GET)
        
                return context
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-03-27
          • 1970-01-01
          • 2011-10-09
          • 2018-01-16
          • 2023-04-04
          • 2019-08-14
          • 2010-11-01
          • 1970-01-01
          相关资源
          最近更新 更多