程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

在 django-admin 中使用父外键、祖父母外键进行搜索

发布于2023-08-21 23:34     阅读(1107)     评论(0)     点赞(17)     收藏(4)


我希望能够搜索一个产品,其类别不直接链接到它,但该类别是祖父或曾祖父等,在实际链接到产品本身的类别的类别树上。我可以实现的唯一方法是使用以下方法,这当然是不可扩展的和正确的方法:

 def get_queryset(self, request):
        queryset = super().get_queryset(request).select_related('brand', 'category', 'category__parent')
        category_name = request.GET.get('category__name', None)

        if category_name:
            # Filter the queryset to include products with the specified category or its ancestors
            queryset = queryset.filter(
                Q(category__name=category_name) |
                Q(category__parent__name=category_name) |
                Q(category__parent__parent__name=category_name) |
                # Add more levels as needed based on the depth of your category tree
            )

        return queryset

这是目前的代码: Product``models.py

class Product(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField(blank=True, null=True)
    description = models.TextField()
    price = models.DecimalField(max_digits=10, decimal_places=2)
    image = models.ImageField(upload_to='product_images/')
    category = models.ForeignKey(Category, on_delete=models.SET_NULL,related_name='product_category', null=True, blank=True)
    brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, related_name='product_brand', null=True, blank=True)
    tags = GenericRelation(TaggedItem, related_query_name='product')
    ratings = GenericRelation(Rating, related_query_name='product')
    active = models.BooleanField(default=True)
    timestamp = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    state = models.CharField(max_length=2, choices=PublishStateOptions.choices, default=PublishStateOptions.DRAFT)
    publish_timestamp = models.DateTimeField(
        # means that the publish_timestamp field will not automatically be set to the current date and time when a new instance of this model is created.
        auto_now_add=False,
        # means that the publish_timestamp field will not automatically be updated to the current date and time every time the model is saved.
        auto_now=False,
        blank=True,
        null=True
    )

    def __str__(self):
        return self.name

Category``models.py

class Category(models.Model):
    name = models.CharField(max_length=255)
    parent = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='subcategories', null=True, blank=True)

    class Meta:
        verbose_name_plural = 'Categories'

    def __str__(self):
        return self.name

Product``admin.py

class ProductAdmin(admin.ModelAdmin):
    list_display = ['name', 'price', 'brand', 'category']
    inlines = [TaggedItemInline]
    list_filter = [
        'brand__name',
        'category__name' 
    ]
    search_fields = ['name', 'price', 'brand__name', 'category__name', 'category__parent__name']

    def get_queryset(self, request):
        return super().get_queryset(request).select_related('brand', 'category', 'category__parent')

    def get_brand_name(self, obj):
        return obj.brand.name if obj.brand else None
    
    def get_category_name(self, obj):
        return obj.category.name if obj.category else None

    get_brand_name.short_description = 'Brand'
    get_category_name.short_description = 'Category'

    # Define the labels for list filters
    list_filter = (
        ('brand', admin.RelatedOnlyFieldListFilter),
        ('category', admin.RelatedOnlyFieldListFilter),
    )

admin.site.register(Product, ProductAdmin)

解决方案


一个小时后,我明白了。

def get_search_results(self, request, queryset, search_term):
    queryset, use_distinct = super().get_search_results(request, queryset, search_term)

    # Search for products based on ascendant category names recursively
    matching_categories = self.find_matching_categories(search_term)
    ascendant_categories = self.get_all_ascendant_categories(matching_categories)
    products_with_ascendant_categories = self.model.objects.filter(category__in=ascendant_categories)
    queryset |= products_with_ascendant_categories

    return queryset, use_distinct

def find_matching_categories(self, search_term):
    # Find categories that match the search term
    return Category.objects.filter(name__icontains=search_term)

def get_all_ascendant_categories(self, categories):
    # Recursively retrieve all ascendant categories
    ascendant_categories = list(categories)
    new_ascendants = Category.objects.filter(parent__in=categories)
    if new_ascendants:
        ascendant_categories.extend(self.get_all_ascendant_categories(new_ascendants))
    return ascendant_categories

当用户搜索产品时,他们现在可以使用该产品类别的上级名称。get_search_results() 方法经过定制以实现此目的。当用户搜索时,代码会识别与搜索词匹配的类别,然后递归地收集这些类别的所有祖先。这可确保搜索结果中包含类别及其后代的产品。



所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:https://www.pythonheidong.com/blog/article/2012824/343a2ab8fbd22f82f9db/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

17 0
收藏该文
已收藏

评论内容:(最多支持255个字符)