Django 管理员:根据父集合和子集合过滤产品

问题描述 投票:0回答:1

我在 Django Collection 模型中使用自引用关系,并且我想修改管理以根据集合过滤产品。目前,当客户端按特定集合过滤产品时,它仅显示与该集合直接关联的产品,而不显示其子集合。我已经修改了管理员中的

get_search_results
函数,但生成的查询似乎在我的过滤器中附加了 AND 条件,而不是使用 OR。

`这是 get_search_results 函数的当前实现:

def get_search_results(自我,请求,查询集,search_term):

collection_filter = request.GET.get('collection__id__exact')
if collection_filter:
    try:
        collection_id = int(collection_filter)
        collection_q = Q(collection_id=collection_id) | Q(collection__parent_id=collection_id)
        queryset = queryset.filter(collection_q)
        print(queryset.query)
    except ValueError:
        pass
print(queryset.query)
return queryset, False
enter code her`

打印结果:

SELECT "shop_product"."id", "shop_product"."created_at", "shop_product"."updated_at", "shop_product"."deleted_at", "shop_product"."unit_price", "shop_product"."inventory", "shop_product"."min_inventory", "shop_product"."collection_id", "shop_product"."promotions_id", "shop_product"."discount_id", "shop_collection"."id", "shop_collection"."created_at", "shop_collection"."updated_at", "shop_collection"."deleted_at", "shop_collection"."parent_id" FROM "shop_product" INNER JOIN "shop_collection" ON ("shop_product"."collection_id" = "shop_collection"."id") LEFT OUTER JOIN "shop_product_translation" ON ("shop_product"."id" = "shop_product_translation"."master_id") WHERE ("shop_product"."collection_id" = 2 AND ("shop_product"."collection_id" = 2 OR "shop_collection"."parent_id" = 2)) ORDER BY "shop_product_translation"."title" ASC, "shop_product"."id" DESC

生成的查询似乎使用 AND 条件,这可能是不包含子集合产品的原因。我如何修改它以使用 OR 条件,并确保父集合和子集合中的产品都包含在过滤结果中?

感谢您对理解和解决此问题的任何帮助。

django django-admin django-queryset django-admin-filters
1个回答
0
投票

这个答案没有使用任何其他库/依赖项(使用 Django)。

假设您有一个与此类似的模型结构:

class ShopCollection(models.Model):
    id = models.AutoField(primary_key=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True, blank=True)
    parent = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True)

    class Meta:
        verbose_name = "Shop Collection"
        verbose_name_plural = "Shop Collections"

    def __str__(self):
        return f"Collection ID: {self.id}"

class ShopProduct(models.Model):
    id = models.AutoField(primary_key=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True, blank=True)
    unit_price = models.DecimalField(max_digits=10, decimal_places=2)
    inventory = models.IntegerField()
    min_inventory = models.IntegerField()
    collection = models.ForeignKey(
        ShopCollection, on_delete=models.CASCADE, related_name="products"
    )
    promotions = models.ForeignKey(
        Promotion, on_delete=models.SET_NULL, null=True, blank=True
    )
    discount = models.ForeignKey(
        Discount, on_delete=models.SET_NULL, null=True, blank=True
    )

    class Meta:
        verbose_name = "Shop Product"
        verbose_name_plural = "Shop Products"

    def __str__(self):
        return f"Product ID: {self.id}"

以下是在 admin.py 中的 ShopProduct ModelAdmin 中进行的更改:

from django.contrib import admin
from django.db.models import Q
from .models import ShopProduct, ShopProductTranslation
from collection.models import ShopCollection


class CollectionFilter(admin.SimpleListFilter):
    title = "Collection"
    parameter_name = "collection"

    def lookups(self, request, model_admin):
        return ShopCollection.objects.values_list("id", "id")

    def queryset(self, request, queryset):
        if self.value():
            try:
                collection_id = self.value()
                queryset = queryset.filter(
                    Q(collection_id=collection_id)
                    | Q(collection__parent_id=collection_id)
                ).distinct()
            except ShopCollection.DoesNotExist:
                pass
        return queryset


class ShopProductAdmin(admin.ModelAdmin):
    list_display = (
        "id",
        "collection",
        "unit_price",
        "inventory",
        "min_inventory",
        "promotions",
        "discount",
        "created_at",
        "updated_at",
        "deleted_at",
    )
    list_filter = (
        CollectionFilter,  # Add the custom filter here
        "promotions",
        "discount",
        "created_at",
        "updated_at",
        "deleted_at",
    )
    search_fields = ("id",)
    ordering = ("id",)


admin.site.register(ShopProduct, ShopProductAdmin)

结果/输出:

收藏清单

集合 ID:1 是集合 ID:2 和集合 ID:4 的父级

集合 ID:3 是集合 ID:5 的父级

产品列表

产品列表按系列 ID 过滤:1

产品列表按系列 ID 过滤:3

产品列表按系列 ID 过滤:2

© www.soinside.com 2019 - 2024. All rights reserved.