【问题标题】:Django,how to filter multiple JSONField data?Django,如何过滤多个 JSONField 数据?
【发布时间】:2023-03-28 06:31:01
【问题描述】:

我将 django 与 postgres 一起使用,我能够在我的视图中添加多个过滤器,但这里的问题是我是否有可能过滤多个具有不同值的相同 jsonfield: 例如我可以过滤localhost:127.0.0.1:products?areaOfUse=residential 那么我有没有可能得到 /products?areaOfUse=residential&areaOfUse=test的结果 所以从这里我需要查询两个不同的 json 对象。

-这是我的看法

class SubcategoriesProductsAPI(APIView):
    # @cache_control(must_revalidate=True, max_age=3600)
    def get (self, request, subCategoryId = None, pk = None):
        try:

            filters = {}
            design  = self.request.query_params.get('design', None)
            dimension = self.request.query_params.get('dimension', None)
            collectionName =  self.request.query_params.get('collectionName', None)
            material = self.request.query_params.get('material',None)
            min_price = self.request.query_params.get('min_price',None)
            max_price = self.request.query_params.get('max_price',None)
            page = self.request.query_params.get('page', None)
            wearLayer = self.request.query_params.get('wearLayer',None)
            areaOfUse = self.request.query_params.getlist('areaOfUse',None)
            productType = self.request.query_params.get('type', None)
            installationMethod =  self.request.query_params.get('installationMethod',None)
            format_type = self.request.query_params.get('format_type',None)
            wearLayer = self.request.query_params.get('wearLayer',None)
            levelOfUse = self.request.query_params.get('levelOfUse',None)

            if design is not None:
                filters['product_options__options__data__design'] = design

            if productType is not None:
                filters['product_options__options__data__type'] = productType
            
            if dimension is not None:
                filters['product_options__options__data__dimensions__contains'] = [{'dimension': dimension}]
           
            if collectionName is not None:
                filters['product_options__options__data__collectionName'] = collectionName
            
            if material is not None:
                filters['product_options__options__data__material'] = material

            if wearLayer is not None:
                filters['product_options__options__data__wearLayer'] = wearLayer

            if installationMethod is not None:
                filters['product_options__options__data__installationMethod'] =installationMethod 

            if format_type is not None:
                filters['product_options__options__data__format'] = format_type

            if areaOfUse is not None:
                filters['product_options__options__data__areaOfUse__contains'] = areaOfUse
                    

            if levelOfUse is not None:
                filters['product_options__options__data__levelOfUse'] = levelOfUse

            if min_price and max_price:
                filters['product_options__options__data__dimensions__range__price'] = float(min_price)
                filters['product_options__options__data__dimensions__0__price__lte'] = float(max_price)

                
            queryset = Products.objects.filter(sub_categories_id = subCategoryId, is_active = True).select_related().filter(**filters)
            
            if not queryset:
                return JsonResponse({ 'status': False, 'msg': 'No products found', 'data': {} }, status=400)
            
            if page is not None:
                paginator = PageNumberPagination()
                page = paginator.paginate_queryset(queryset, request)

                if page is not None:
                    serializer = ProductSerializer(page, many=True)
                    return JsonResponse({ 'status': True, 'msg': 'Succesfully retrived products ', 'data': serializer.data,  'count': paginator.page.paginator.count, 'previous':paginator.get_previous_link(), 'next':paginator.get_next_link() }, status=200)
            serializer = ProductSerializer(queryset, many=True)
            return JsonResponse({ 'status': True, 'msg': 'Succesfully retrived products ', 'data': serializer.data }, status=200)
        except Products.DoesNotExist:
            return JsonResponse({ 'status': False, 'msg': 'Internal system error', 'data': {}}, status=500)

【问题讨论】:

    标签: json django postgresql django-filters django-jsonfield


    【解决方案1】:
    areaOfUse = self.request.query_params.getlist('areaOfUse[]',None)
    

    /products?areaOfUse%5B%5D=residential&areaOfUse%5B%5D=test

    import operator
    from django.db.models import Q
    from functools import reduce
    queryset = Products.objects.filter(sub_categories_id = subCategoryId, is_active = True).select_related().filter(**filters)
    if areaOfUse:
        queryset.filter(
            reduce(
                operator.and_,
                (Q(product_options__options__data__areaOfUse__contains=x) for x in areaOfUse)
            )
        )
    

    【讨论】:

    • 在这种情况下仍然没有运气,我没有得到任何结果。或者我应该用不同的东西更改包含:if areaOfUse is not None: filters['product_options__options__data__areaOfUse__contains'] = areaOfUse
    • 你的 areaOfUse 变量是一个列表
    • 根据您的预期结果使用 operator.and_ 或 operator.or_。
    • 感谢@Agawane,我得以修复,他的回答非常有帮助。
    猜你喜欢
    • 2016-07-23
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    • 2022-08-14
    • 2020-10-08
    • 2016-03-25
    相关资源
    最近更新 更多