【问题标题】:Django urls and filtering , the right way to achieve thisDjango urls 和过滤,实现这一点的正确方法
【发布时间】:2020-04-30 09:51:49
【问题描述】:

我有一个用于搜索汽车的网络应用。在登录页面上,我可以输入关键字并搜索,也可以转到显示所有带有过滤器的数据的链接。 所以我的网址,

url(r'^cars/$', search, name='search'), ==> does an elastic search
url(r'^select/', select, name='select'),==> has links to filter results and pass query set

当我输入关键字(比如奥迪)并搜索时,URL 变为 localhost:8000/cars/?search=Audi 如果我点击链接,它只会显示 localhost:8000/select/

这两个视图(搜索和选择)都呈现相同的模板。 现在,我想过滤结果或添加更多条件。这样做的正确方法应该是什么? 我因做这个项目而受到启发的网站之一只是重定向到 /cars?search=Audi 并单击任何链接以过滤重定向到 /cars/Audi/BMW/Sedan 这在 Django 中可能吗?

这里是选择视图代码。我还在学习Django和python,所以,请多多包涵。

def select(request):
    q1 = request.GET.get('brand')
    q2 = request.GET.get('model')
    q3 = request.GET.get('bodyStyle')
    q4 = request.GET.get('budget[]')
    q5 = request.GET.get('transmission')
    page = request.GET.get('page', 1)

    print(q1)
    s1 = request.POST.get('sortBy')



    budarray = request.GET.getlist('budget')
    brandarray = request.GET.getlist('brand')
    modelarray = request.GET.getlist('model')
    bodyarray = request.GET.getlist('bodyStyle')
    transmissionarray = request.GET.getlist('transmission')


    cars = product_details.objects.all()
    posturl=""


    if len(brandarray)>0:
                    brandarray=list(dict.fromkeys(brandarray))
                    cars = cars.filter(brand_name__in=brandarray)


    if len(modelarray)>0:
                    cars = cars.filter(model_name__in=modelarray)

    if len(bodyarray)>0:
                    cars = cars.filter(bodystyle__in=bodyarray)

    if len(transmissionarray)>0:
                    cars = cars.filter(transmission__in=transmissionarray)



    minp=0
    maxp=0
    denom=""

    arraybud =[]
    if len(budarray)>0:
                for items in budarray:
                    budgetval = GetBudget(items)


                    minp=int(budgetval[0])
                    maxp=int(budgetval[1])
                    denom=budgetval[2]
                    arraybud.append(minp)
                    arraybud.append(maxp)



    minprice=0
    maxprice=0

    if len(budarray)>0:
        minprice=min(arraybud)
        maxprice=max(arraybud)
       if minp>100:
            cars=cars.filter(min_price__gt=minprice).filter(denomination='Crore')
            denom="Crores"
        else:
            denom="Lakhs"
            cars=cars.filter(min_price__gt=minprice,min_price__lt=maxprice).filter(denomination=denom)

    sort = GetOrderBy(s1)


    if sort =="nothing":
        cars = cars.order_by('model_name','min_price')
    else:
        cars = cars.order_by('model_name',sort)

    cars = cars.distinct('model_name')

    totalResult = cars.count()
    if totalResult >= 50:
        paginator = Paginator(cars, 25)
    else:
        paginator = Paginator(cars, 10)

    try:
        cars = paginator.page(page)
    except PageNotAnInteger:
        cars = paginator.page(1)
    except EmptyPage:
        cars = paginator.page(paginator.num_pages)

    print(request.get_full_path)

    _brands = products.objects.all()

    _models= product_models.objects.all()

    _bodystyles = product_bodystyle.objects.all()
    posturl = "Y"

    hyundaicars = product_details.objects.filter(brand_name='Hyundai').distinct('model_name')
    tatamotors = product_details.objects.filter(brand_name='Tata').distinct('model_name')
    maruticars = product_details.objects.filter(brand_name='Maruti Suzuki').distinct('model_name')
    mahindracars = product_details.objects.filter(brand_name='Mahindra').distinct('model_name')
    hondacars = product_details.objects.filter(brand_name='Honda').distinct('model_name')

    for (i, item) in enumerate(budarray):
        if item == "1":
            budarray[i] = "1 - 5 Lakhs"
        if item == "2":
            budarray[i] = "5 - 10 Lakhs"
        if item == "3":
            budarray[i] = "10 - 15 Lakhs"
        if item == "4":
            budarray[i] = "15 - 20 Lakhs"
        if item == "5":
            budarray[i] = "20 - 25 Lakhs"
        if item == "6":
            budarray[i] = "25 - 50 Lakhs"
        if item == "7":
            budarray[i] = "50 - 99 Lakhs"
        if item == "8":
            budarray[i] = "Above 1 Crore"


    return render(request, 'search/search_results.html', carsdetails) 

【问题讨论】:

    标签: django elasticsearch django-queryset django-filter


    【解决方案1】:

    可以这样做:

    文件views.py:

    from rest_framework.generics import ListAPIView
    from rest_framework.filters import DjangoFilterBackend, OrderingFilter
    from rest_framework.renderers import TemplateHTMLRenderer
    
    class RetrieveCarView(ListAPIView):
        queryset = product_details.objects.all()
    
        model = product_details
        filter_class = ProductDetailsFilter
        filter_backends = (OrderingFilter, DjangoFilterBackend)
        ordering_fields = ('brand', )
        pagination_class = LargeResultsSetPagination
        serializer_class = ProductDetailsSerializer
        renderer_classes = (TemplateHTMLRenderer,)
        template_name = 'search/search_results.html'
    

    文件 serializers.py

    class ProductDetailsSerializer(ModelSerializer):
        class Meta:
            model = DeviceAttachment
            fields = ('brand', 'model', 'bodyStyle', 'transmission')
            # in fields it`s needed to list fields from product_details which will be shown in html template
    

    文件过滤器.py

    import rest_framework_filters as filters
    
    
    class  ProductDetailsFilter(filters.FilterSet):
        # here are defined fields by which there is a need to filter
        brand = filters.AllLookupsFilter(name='brand')
        bodyStyle = filters.AllLookupsFilter(name='bodyStyle')
        transmission = filters.AllLookupsFilter(name='transmission')
        budget = filters.AllLookupsFilter(name='budget')
        model = filters.AllLookupsFilter(name='model')
    
    class Meta:
        model = product_details
        fields = {
            'brand': ['exact', 'in'],
            'bodyStyle: ['exact', 'in'],
            'transmission': ['exact', 'in'],
            'budget': ['exact', 'in'],
            'model': ['exact', 'in']
        }
    

    文件 paginators.py

    class from rest_framework.pagination import PageNumberPagination
    from rest_framework.response import Response
    
    
    class LargeResultsSetPagination(PageNumberPagination):
        page_size = 100
        page_size_query_param = 'page_size'
        max_page_size = 1000
    
    def get_paginated_response(self, data):
        return Response(data)
    

    最后你就可以这样过滤了:

    select/?model=Audi&transmission__in=1,2&page=1&page_size=1

    【讨论】:

      猜你喜欢
      • 2017-07-02
      • 1970-01-01
      • 1970-01-01
      • 2012-11-11
      • 1970-01-01
      • 2019-09-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-15
      相关资源
      最近更新 更多