我是Django的新手,我正在尝试通过Category
模型访问属于类别的产品。我在Product
中使用外键进行分类。
这些是我的模型:
class Category(models.Model):
name = models.CharField(max_length=140)
slug = models.SlugField(blank=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("shop:category", kwargs=
{"category_slug": self.slug})
class Product(models.Model):
category = models.ForeignKey(Category,
on_delete=models.CASCADE)
brand = models.ForeignKey(Brand,
on_delete=models.CASCADE)
title = models.CharField(max_length=200)
slug = models.SlugField()
description = models.TextField()
image = models.ImageField(upload_to=image_name)
price = models.PositiveIntegerField()
avaliable = models.BooleanField(default=True)
def get_absolute_url(self):
return reverse("shop:product", kwargs={
"product_slug": self.slug,
"product_ctgr_slug":
self.category.slug,})
我的观点:
class CategoryDetailView(DetailView):
model = Category
category_products = Category.product_set.all()
slug_url_kwarg = "category_slug"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['categories'] = self.categories
context['category_products'] = self.category_products
return context
但是Django给了我AttributeError: 'ReverseManyToOneDescriptor' object has no attribute 'all'
。
我在做什么错了?
答案 0 :(得分:2)
这可能有帮助:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
instance = self.get_object()
context['categories'] = self.categories
context['category_products'] = instance.product_set.all()
return context
答案 1 :(得分:1)
您可以使用product_set
作为Django默认创建的相关名称,也可以自己更好地创建相关名称。 产品属于类别,但是类别可以具有许多 product 。遵循这一原则,并使您的查询易于阅读。
为此,请在类category
中为Product
设置相关名称:
category = models.ForeignKey(
Category,
on_delete=models.CASCADE,
related_name='products'
)
现在您必须在views.py
中进行一些更改。
class CategoryDetailView(DetailView):
model = Category
# remove the line below
category_products = Category.product_set.all()
# don't prefix the fields like this, it's ugly and redundant
# call it just slug, not category_slug, adjust in urls.py
slug_url_kwarg = "category_slug"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# where did you get self.categories?
context['categories'] = self.categories
# and this won't work anymore too
context['category_products'] = self.category_products
return context
在CategoryDetailView
中,您将只显示一个类别。它是详细视图-仅表示一个对象。因此,您不会使用类别之类的东西。该对象在方法中可用。这是我们重写它的方式:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
products = self.object.products.all()
context['products'] = products
return context
答案 2 :(得分:0)
真正的问题是原始发布者试图从类而不是从实例调用RelatedManager.all()函数。
category_products = Category.product_set.all()
Category 是类名。既然是类,它不会也不可能知道单个实例的相关产品。
您必须从实例而不是类本身调用 RelatedManagers.all() 函数。