Django-DetailView-`get_object`函数混淆 [英] Django - DetailView - `get_object` function confusion

查看:85
本文介绍了Django-DetailView-`get_object`函数混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是CBV的新手.不确定为什么这不起作用...

I'm new to CBV. Not sure why this isn't working...

views.py

class ItemDetailView(DetailView):
    '''display an individual item'''
    model = Item
    template_name = 'boutique/item.html'
    context_object_name = 'item'

    # With model specified, following code would be redundant, wouldn't it?? However...
    # def get_object(self):
        # return get_object_or_404(Item, pk=self.kwargs.get('item_pk'))

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # add categories for navbar link texts
        context['categories'] = Category.objects.all()

        print('\ncontext= ', context, '\n')
        return context

AttributeError at /item_8/ Generic detail view ItemDetailView must be called with either an object pk or a slug in the URLconf.

并且上下文没有被打印出来.

AttributeError at /item_8/ Generic detail view ItemDetailView must be called with either an object pk or a slug in the URLconf.

And the context isn't being printed out.

如果将get_object添加到代码中,则可以正常工作:

If I add get_object to the code, it's working fine:


class ItemDetailView(DetailView):
    '''display an individual item'''
    # model = Item
    template_name = 'boutique/item.html'
    # context_object_name = 'item'

    def get_object(self):
        return get_object_or_404(Item, pk=self.kwargs.get('item_pk'))

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # add categories for navbar link texts
        context['categories'] = Category.objects.all()

        print('\ncontext= ', context, '\n')
        return context


但是,如果我将get_object函数更改为:


However, if I changed get_object function to:

    def get_object(self):
        obj = super().get_object()
        obj = get_object_or_404(Item, pk=self.kwargs.get('item_pk'))
        # obj = obj.filter(pk=self.kwargs.get('item_pk')) # doesn't work, same error
        # obj = obj.get(pk=self.kwargs.get('item_pk')) # doesn't work, same error

        return obj

ImproperlyConfigured at /item_8/ ItemDetailView is missing a QuerySet. Define ItemDetailView.model, ItemDetailView.queryset, or override ItemDetailView.get_queryset().

我很困惑... DetailView应该可以工作,而不必完全不定义get_object?

ImproperlyConfigured at /item_8/ ItemDetailView is missing a QuerySet. Define ItemDetailView.model, ItemDetailView.queryset, or override ItemDetailView.get_queryset().

I'm confused... DetailView should work without having to define get_object at all no??

url.py

app_name = 'boutique'
urlpatterns = [
    # show index page
    path('', views.IndexView.as_view(), name='index'),

    # show a specific item
    path('item_<int:item_pk>/', views.ItemDetailView.as_view(), name='item'),

    # show categories of products for men or women
    path('<slug:gender>/', views.CategoryListView.as_view(), name='show-all'),

    # show a specific category for men or women
    path('<slug:gender>/cat_<int:category_pk>/', views.CategoryListView.as_view(), name='category'),

    # show a specific subcategory under a specific category for men or women
    path('<slug:gender>/cat_<int:category_pk>/subcat_<int:subcategory_pk>/', views.CategoryListView.as_view(), name='subcategory'),

]

models.py

models.py

class Item(models.Model):
    '''Each item represents a product'''
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    subcategory = models.ForeignKey(
        SubCategory, on_delete=models.CASCADE, null=True, blank=True)
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    price = models.IntegerField(default='0')
    discount = models.IntegerField(null=True, blank=True)
    uploaded_date = models.DateTimeField(
        auto_now_add=True, null=True, blank=True)

    class Meta:
        ordering = ['-uploaded_date']

    def __str__(self):
        return self.name

    def discounted_price(self):
        '''to calculate the price after discount'''
        return int(self.price * (100 - self.discount) * 0.01)

    def get_item_url(self):
        return reverse('boutique:item', kwargs={'item_pk': self.pk})

item.html

item.html

<!-- display each item in its own box -->
<div class="col-6 col-md-4 col-lg-3 px-1 px-sm-2 d-flex flex-column">

    <!-- image anchor -->
    <a href="{{ item.get_item_url }}">
        <img class="rounded-sm" src="{{item.itemimage_set.first.image.url}}" width="100%"
    alt=""></a>
    <!-- /image anchor -->

    <!-- item price tag -->
    <div class="text-left p-1 mt-auto" style="font-size: 16px;">
        <div class="font-weight-light pt-2">
            <a href="{{ item.get_item_url }}" class="text-dark mb-1">{{item}}</a>
        </div>

        <div class="font-weight-lighter">
            {% if item.discount %}

            <p>
                <strike class="text-muted">&#8381;&nbsp;{{item.price}}</strike>
                <b class="text-danger">&#8381;&nbsp;{{item.discounted_price}}</b>
                <small class="text-danger">(-{{item.discount}}%)</small>
            </p>

            {% else %}
            <p>&#8381;&nbsp;{{item.price}}</p>

            {% endif %}
        </div>
    </div>
    <!-- /item price tag -->

</div>

推荐答案

您的第一个示例是正确的,您无需显式定义get_object(),但应在URL路径中使用pk参数而不是item_pk使用详细信息CBV时:

Your first example is correct, you don't need to define get_object() explicitly but you should use pk argument instead of item_pk in url path when using details CBV:

path('item_<int:pk>/', views.ItemDetailView.as_view(), name='item'),

默认情况下,由于get_object()方法使用self.kwargs["pk"]搜索对象.

Since by default get_object() method using self.kwargs["pk"] to search object.

如果您仍要使用item_pk,则需要使用

If you still want to use item_pk you need to specify in in view using pk_url_kwarg:

class ItemDetailView(DetailView):
    pk_url_kwarg = 'item_pk'

来自文档:

此处的URLconf使用命名的组pk-该名称是默认名称 DetailView用于查找用于以下操作的主键的值的名称 过滤查询集.

The URLconf here uses the named group pk - this name is the default name that DetailView uses to find the value of the primary key used to filter the queryset.

如果您想给群组打电话,可以设置pk_url_kwarg 在视图上.可以在DetailView的参考中找到更多详细信息

If you want to call the group something else, you can set pk_url_kwarg on the view. More details can be found in the reference for DetailView

这篇关于Django-DetailView-`get_object`函数混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆