【问题标题】:Get unique outputs from combining more than one Django filters通过组合多个 Django 过滤器获得独特的输出
【发布时间】:2021-08-08 09:26:29
【问题描述】:

因此,我试图在我的网站上创建一个搜索引擎,用户可以在其中输入查询,然后在产品namedescription 中显示查询存在的结果。我的产品型号如下:-

'''Product model to store the details of all the products'''
class Product(models.Model):

    # Define the fields of the product model
    name = models.CharField(max_length=100)
    price = models.IntegerField(default=0)
    quantity = models.IntegerField(default=0)
    description = models.CharField(max_length=200, default='', null=True, blank=True)
    image = models.ImageField(upload_to='uploads/images/products')
    category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1)    # Foriegn key with Category Model
    store = models.ForeignKey(Store, on_delete=models.CASCADE, default=1)

现在,我创建了一个搜索过滤器,我先按名称过滤,然后按描述过滤,然后组合结果以返回查询集。问题是有时可以在名称和描述中找到查询,所以我会得到这样的重复条目

我在 ProductView 中的过滤代码如下:-

class ProductView(generics.ListAPIView):
    ''' Product View to return the details of all the products and filter by ID or string '''

    # Define class variables 
    queryset = []

    # Manage a get request
    def get(self, request):
        
        ''' Display all the products in our database if no id is passed 
            and if a store ID and search is passed then use those parameters'''
        
        # Get all the parameters sent in the data 
        store_id = request.GET.get('store_id')
        search_query = request.GET.get('search')
        category = request.GET.get('category')

        print(store_id, search_query, category)
        queryset = Product.get_all_products()
        
        # Apply filters to the data
        if store_id:
            queryset = queryset.filter(store=store_id)
        
        if category:
            queryset = queryset.filter(category=category)
        
        if search_query: 
            

            # THIS IS WHERE THE SEARCH FILTERING SHOULD HAPPEN

            names = queryset.filter(name__icontains=search_query)
            descriptions = queryset.filter(description__icontains=search_query)

            queryset = list(chain(names, descriptions))
        
        return Response(ProductSerializer(queryset, many = True).data)
        

我希望只能得到一个结果,因为它是相同的产品。有没有办法只能将不同的结果保存在查询集中。我做了一个循环,检查descriptions 中的结果是否该项目已经存在于名称中,但效果不是很好。我该如何解决这个问题?

【问题讨论】:

  • 您使用的是基于类的视图还是基于函数的视图?
  • 基于类的视图
  • 好的,检查下面给出的答案。

标签: python django django-rest-framework django-queryset


【解决方案1】:

你有两个问题。

首先,您不应该像这样评估和合并两个查询集结果。

如果要选择名称或描述为 icontainingsearch_query 的所有实体,请使用 Q 对象。

要仅选择查询集中的唯一对象,请使用distinct

所以你可以把最后几行改成这样。

        if search_query:
            queryset = queryset.filter(
                Q(name__icontains=search_query) | Q(description__icontains=search_query)
            )
        
        queryset = queryset.distinct()  # probably won't be needed anymore

【讨论】:

  • 是的,这就是我要找的。谢谢。它更整洁、更高效。
【解决方案2】:

我添加了一个 forloop 来完成这项工作,但如果有人有更好的解决方案,请将其留在 cmets 中。这是我写的最后一个视图。

class ProductView(generics.ListAPIView):
    ''' Product View to return the details of all the products and filter by ID or string '''

    # Define class variables 
    serializer_class = ProductSerializer
    queryset = Product.objects.all()

    search_fields = ['name','description']
    filter_backends = (SearchFilter,)
    queryset = []

    # Manage a get request
    def get(self, request):
        
        ''' Display all the products in our database if no id is passed 
            and if a store ID and search is passed then use those parameters'''
        
        # Get all the parameters sent in the data 
        store_id = request.GET.get('store_id', None)
        search_query = request.GET.get('search')
        category = request.GET.get('category')

        print(store_id, search_query, category)
        queryset = Product.get_all_products()
        
        # Apply filters to the data
        if store_id:
            queryset = queryset.filter(store=store_id)
        
        if category:
            queryset = queryset.filter(category=category)
        
        if search_query: 
            pass 
            names = queryset.filter(name__icontains=search_query)
            descriptions = queryset.filter(description__icontains=search_query)

            # Iterate through the names and get all ids 
            ids = []
            for i in range(len(names)):
                ids.append(names[i].id)
                print(type(names[i].id), print(type(names[i])))
            
            # iterate through descriptions 
            for i in range(len(descriptions)): 
                if descriptions[i].id not in ids:
                    ids.append(descriptions[i].id)
            
            queryset = Product.objects.filter(id__in=ids)
        
        return Response(ProductSerializer(queryset, many = True).data)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多