了解 Django Class-Based(DetailView 和 View)
Understanding Django Class-Based (DetailView and View)
我正在将一些基于函数的视图转换为基于 Class 的视图,以使我的视图更具可读性。但是我不太了解 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
由于您的 slug 字段名为 slug
,您只需在详细视图中指定 model
和 template_name
。详细视图将负责获取带有该鼻涕虫的人。
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
在上面,我假设用card_is_chosen
修饰dispatch
方法是可以的。如果不是这种情况,您可以改为添加 method_decorator(card_is_chosen, name='get')
。我添加了一个 get_context_data
- 上面的代码不需要它,但它可能对你的问题中你没有显示的某些 ...
代码有用。
如果您重写 get
方法,我会使用通常的签名 def get(self, request, *args, **kwargs):
然后为 self.kwargs
获取 slug
def get(self, request, *args, **kwargs):
slug = self.kwargs['slug']
通常应避免为通用 class-based-views 覆盖 get
和 post
。您冒着失去功能或不得不复制代码的风险。通常有更具体的属性或方法可以覆盖。
最后,不要假设基于 class 的视图总是更好。就个人而言,我会发现以下 function-based-view 比您的 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, {...})
我们可以使用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)
使用 variable/name object
访问模板中的对象
好吧,使用 CBV 的优势在于您可以 re-use 来自其他 django CBV 或您自己的 classes/mixins 的功能。这导致有更多的 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 的对象实例。
我正在将一些基于函数的视图转换为基于 Class 的视图,以使我的视图更具可读性。但是我不太了解 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
由于您的 slug 字段名为 slug
,您只需在详细视图中指定 model
和 template_name
。详细视图将负责获取带有该鼻涕虫的人。
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
在上面,我假设用card_is_chosen
修饰dispatch
方法是可以的。如果不是这种情况,您可以改为添加 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']
通常应避免为通用 class-based-views 覆盖 get
和 post
。您冒着失去功能或不得不复制代码的风险。通常有更具体的属性或方法可以覆盖。
最后,不要假设基于 class 的视图总是更好。就个人而言,我会发现以下 function-based-view 比您的 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, {...})
我们可以使用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)
使用 variable/name object
好吧,使用 CBV 的优势在于您可以 re-use 来自其他 django CBV 或您自己的 classes/mixins 的功能。这导致有更多的 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 的对象实例。