【问题标题】:How can I gather all objects, from all models, within one class based view in django 2.2如何在 django 2.2 的一个基于类的视图中收集所有模型中的所有对象
【发布时间】:2020-04-10 04:16:27
【问题描述】:

我的一个朋友正试图在一个视图中收集他的每个模型的所有数据,以显示在一个模板上,并将“slug”作为 URL。

他目前有一个基于类的视图,如下所示:

from itertools import chain


class ProductDetailView(DetailView):
    queryset1 = BooksProduct.objects.all()
    queryset2 = ClothingProduct.objects.all()
    queryset3 = FurnitureProduct.objects.all()
    queryset4 = DecoratingProduct.objects.all()
    queryset = chain(queryset1, queryset2, queryset3, queryset4)
    template_name = 'products/detail.html'

网址如下所示:

urlpatterns =[
    path('product-detail/<slug>/', ProductDetailView.as_view(), name='product-detail'),
]

四种不同的模型看起来都非常相似:

class BookProduct(models.Model):

    slug = models.SlugField(max_length=40)
    image = models.ImageField(upload_to='media')
    title = models.CharField(max_length=150)
    description = models.TextField()
    short_description = models.CharField(max_length=300)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    stock_quantity = models.PositiveIntegerField()
    in_stock = models.BooleanField(default=True)
    main_category = models.CharField(choices=PRODUCT_CATEGORY_CHOICES, max_length=2, default='FW')
    brand = models.CharField(choices=TOY_BRAND_CHOICES, max_length=2, default='NB')
    on_sale = models.BooleanField(default=False)
    date_added = models.DateTimeField(auto_now_add=True, blank=True)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-date_added']

    def get_absolute_url(self):
        return reverse("products:product-detail", kwargs={
            'slug': self.slug
        })

目前,单击单个产品以获取 product-detail.html 视图会导致此错误:

'itertools.chain' 对象没有属性'all'

他如何能够将每个模型的所有产品汇总到一个视图中?

DetailView 已更改为 ListView ,这使产品详细信息呈现到模板中,但是当您尝试刷新页面时,或按下后退按钮并重新单击产品以再次查看详细信息页面,它消失了,直到他再次重置服务器。

HTML 模板如下所示:

<section id="detail-view">
    <div class="container">
        <div class="row">
            <div class="col-6">
                <img src="{{ product.image.url }}" alt="{{ product.title }}">
            </div>
            <div class="col-6">
                {% for product in object_list %}
                <h1>{{ product.title }}</h1>
                <strong>£{{ product.price }}</strong>
                <hr class="newhr">
                <a href="" class="btn btn-customtwo btn-block">ADD TO BASKET</a>
                <div class="detail-desc-box">
                    <p>{{ product.description }}</p>
                </div>
                {% endfor %}
            </div>
        </div>
    </div>
</section>

视图现在看起来像这样:

from itertools import chain


class ProductDetailView(ListView):
    queryset1 = BooksProduct.objects.all()
    queryset2 = ClothingProduct.objects.all()
    queryset3 = FurnitureProduct.objects.all()
    queryset4 = DecoratingProduct.objects.all()
    queryset = chain(queryset1, queryset2, queryset3, queryset4)
    template_name = 'products/detail.html'

亲切的问候

【问题讨论】:

    标签: django django-models django-views django-queryset django-2.2


    【解决方案1】:

    我认为您无法像希望的那样开箱即用地使用通用视图。原因是因为 DetailView 专门用于显示单个模型实例。您正在尝试显示多个。

    我建议将其切换为ListView,为视图提供一个额外的 url 关键字参数以指定 slug,然后执行以下操作之一:

    1. 使用.union() 对数据库进行一次查询并处理文档中详述的该方法的约束。
    2. 重构您的models to use inheritance 并根据通用模型进行选择。

    注意: 您当前遇到的错误是因为您有效地将 DetailView.queryset 的类型从 QuerySet 更改为生成器。通用视图的其余部分期望某些成员存在,例如 .all()

    【讨论】:

    • 因此,他从 DetailView 更改为 ListView 并立即开始在 detail.html 页面中呈现信息,但是如果我们刷新页面,信息完全消失并且没有重新出现。
    • 我将在上面附上他的 HTML 文档,以便清楚地说明他是如何引用对象的......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多