如何编写Django模型查询以获取产品列表,包含是否在愿望清单中?

1 投票
2 回答
38 浏览
提问于 2025-04-14 16:36

models.py

models.py 
class Product(models.Model):
    code = models.CharField(max_length=50, default=None, null=True, blank=True, unique=True)
    name = models.CharField(max_length=100)
    category_id = models.ForeignKey(category, on_delete=models.CASCADE)   
    size_id = models.ForeignKey(size, on_delete=models.CASCADE)
    cost = models.IntegerField()
    tax_id = models.ForeignKey(Tax, on_delete=models.CASCADE)
    price = models.IntegerField()

class wishlist(models.Model):
    product_id = models.ForeignKey(Product,  on_delete=models.CASCADE, 
                                      error_messages = {'unique': 'This Product is already in exist',})
    user_id = models.ForeignKey(Account, on_delete=models.CASCADE)
    create_at = models.DateTimeField(auto_now_add=True)

我想要获取所有的产品,就像使用 product.objects.all() 这样,同时检查特定的产品是否在购物车和愿望清单中。

2 个回答

0

你可以使用一个叫做 Exists 表达式 [Django-doc] 来做一些操作:

from django.db.models import OuterRef, Exists

Product.objects.annotate(
    in_wishlist=Exists(
        wishlist.objects.filter(
            product_id=OuterRef('pk'), user_id_id=request.user.id
        )
    )
)

从这个查询结果中得到的 Product 对象会多一个属性 .in_wishlist,如果有一个 wishlist 对象的 user_id_id 是当前用户的 ID,并且 product_id 是对应的产品,那么这个属性的值就是 True


注意:通常情况下,ForeignKey 字段后面不需要加 …_id 后缀,因为 Django 会自动添加一个带有 …_id 后缀的“兄弟”字段。所以应该用 user,而不是 user_id


注意:通常建议使用 settings.AUTH_USER_MODEL [Django-doc] 来引用用户模型,而不是直接使用 User 模型 [Django-doc]。想了解更多信息,可以查看文档中关于 引用 User 模型 的部分


注意:在 Django 中,模型名称使用 PascalCase 格式,而不是 snake_case 格式,所以你可能想把模型的名字从 wishlist 改成 WishList

0

你的模型设置有问题。
一个愿望清单只能分配给一个用户,这样使用ForeignKey是对的。
但是,根据你上面的代码,你把一个愿望清单只分配给了一个产品。因为你使用了ForeignKey(和用户的关系是一样的),所以你的愿望清单不能包含多个产品。

相反,你应该使用多对多关系。因为一个愿望清单可以包含多个产品,而一个产品也可以被多个愿望清单包含。

class wishlist(models.Model):
    products = models.ManyToManyField(Product)
    user_id = models.ForeignKey(Account, on_delete=models.CASCADE)
    create_at = models.DateTimeField(auto_now_add=True)
from django.db.models import Prefetch

# Prefetch related products in cart and wishlist for the user
cart_prefetch = Prefetch('cart_set', queryset=Cart.objects.filter(user=user), to_attr='user_cart')
wishlist_prefetch = Prefetch('wishlist_set', queryset=Wishlist.objects.filter(user=user), to_attr='user_wishlist')

products = Product.objects.prefetch_related(cart_prefetch, wishlist_prefetch).all()

# Iterate over products
for product in products:
    in_cart = any(cart for cart in getattr(product, 'user_cart', []))
    in_wishlist = any(wishlist for wishlist in getattr(product, 'user_wishlist', []))
    print(f"Product {product.name} is in cart: {in_cart}, is in wishlist: {in_wishlist}")

撰写回答