Django-DetailView-`get_object`函数混淆 [英] Django - DetailView - `get_object` function confusion
问题描述
我是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">₽ {{item.price}}</strike>
<b class="text-danger">₽ {{item.discounted_price}}</b>
<small class="text-danger">(-{{item.discount}}%)</small>
</p>
{% else %}
<p>₽ {{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.
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屋!