我正在将一些基于功能的视图转换为基于类的视图,以使我的视图更具可读性。但是我对DetailView
的使用并不是很了解,以及如何将它实际集成到我的代码中以便将slug
传递给我的函数。
目前,我正在使用View
并将slug
传递给我的函数,如下所示:
#urls.py
path('preview/<slug:slug>/', views.Preview.as_view(), name='toPreview')
#views.py
@method_decorator(auth0_login_required, name='dispatch')
class Preview(View):
template_name = 'authenticated/preview.html'
@card_is_chosen
def get(self, slug, request, *args, **kwargs):
person = get_object_or_404(Person, slug=slug, status=True)
...
return render(request, self.template_name, {...})
我也不太确定这是不是最好的做法,以防那么DetailView会提供什么?
编辑:在评论中提到使用DetailView,我该如何解决此错误?
#urls.py
path('preview/<slug:slug>/', views.Preview.as_view(), name='toPreview')
#views.py
@method_decorator(auth0_login_required, name='dispatch')
class Preview(DetailView):
model = Person
template_name = 'preview.html'
@card_is_chosen
def get(self, request, *args, **kwargs):
print(slug)
#slug is not defined, how should I fetch slug parameter?
...
return render(request, self.template_name, {...})
回溯:
File "C:\Users\...\Desktop\env\src\...\apps\businesscards\decorators.py", line 60, in wrap
return function(self, request, slug, *args, **kwargs)
File "C:\Users\...\Desktop\env\src\...\apps\businesscards\views.py", line 160, in get
person = get_object_or_404(Person, slug=slug, status=True)
NameError: name 'slug' is not defined
答案 0 :(得分:3)
由于您的slug字段被称为slug
,您只需在详细信息视图中指定model
和template_name
即可。细节视图将负责抓取那个slug的人。
from django.views.generic import DetailView
@method_decorator([auth0_login_required, card_is_chosen] name='dispatch')
class PersonDetailView(DetailView):
model = Person
template_name = 'authenticated/preview.html'
def get_context_data(self, **kwargs):
"""
get_context_data is one of the important hooks in generic class
based views. It lets you add extra variables to the template context
"""
context = super(PersonDetailView, self).get_context_data(**kwargs)
context['extra'] = 'extra value'
return context
在上面,我假设用dispatch
装饰card_is_chosen
方法是可以的。如果不是这种情况,您可以添加method_decorator(card_is_chosen, name='get')
。我添加了一个get_context_data
- 上面的代码不需要它,但它可能对您未提供的问题中的某些...
代码有用。
如果您覆盖get
方法,我会使用通常的签名def get(self, request, *args, **kwargs):
,然后获取self.kwargs
def get(self, request, *args, **kwargs):
slug = self.kwargs['slug']
对于基于类的通用视图,通常应该避免覆盖get
和post
。您可能会失去功能或不得不重复代码。通常可以覆盖更具体的属性或方法。
最后,不要认为基于类的视图总是更好。就个人而言,我会发现以下基于函数的视图比Preview
视图更容易阅读。
@auth0_login_required
@card_is_chosen
def person(request, slug):
person = get_object_or_404(Person, slug=slug, status=True)
template_name = 'authenticated/preview.html'
...
return render(request, template_name, {...})
答案 1 :(得分:2)
我们可以使用function HidePopup(modalId) {
$(modalId).modal('hide');
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
}
,如下所示
DetailView
使用变量/名称from django.views.generic import DetailView
@method_decorator(login_required, name='dispatch')
@method_decorator(card_is_chosen, name='get')
class Preview(DetailView):
template_name = 'authenticated/preview.html'
def get_object(self):
return get_object_or_404(Person, slug=self.kwargs['slug'], status=True)
答案 2 :(得分:0)
使用CBV的优势在于您可以重复使用其他django CBV或您自己的类/ mixin的功能。这导致具有更多DRY代码。
我已经写了一篇冗长的教程,我建议在开始使用CBV之前阅读这篇文章:https://spapas.github.io/2018/03/19/comprehensive-django-cbv-guide/
现在,根据您的具体示例:您很少需要继承View
- 而是继承View的子类,例如DetailView
,如您所述。现在,您可以像这样实现Preview
视图:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import DetailView
class Preview(LoginRequiredMixin, View):
template_name = 'authenticated/preview.html'
mode = Person
我不确定@card_is_chosen
装饰器的作用,但上面的功能与您的示例相同(我已auth0_login_required
改为login_required
,因为我也不知道auth0_login_required
做了什么。请注意,您不需要重新定义get,也不需要调用任何代码来根据slug检索对象实例。