我在 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)。
假设您有一个与此类似的模型结构:
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