理解Django基于类(DetailView和View)

时间:2018-03-28 12:19:02

标签: django django-views django-class-based-views

我正在将一些基于功能的视图转换为基于类的视图,以使我的视图更具可读性。但是我对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

3 个答案:

答案 0 :(得分:3)

由于您的slug字段被称为slug,您只需在详细信息视图中指定modeltemplate_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

的slug
def get(self, request, *args, **kwargs):
    slug = self.kwargs['slug']

对于基于类的通用视图,通常应该避免覆盖getpost。您可能会失去功能或不得不重复代码。通常可以覆盖更具体的属性或方法。

最后,不要认为基于类的视图总是更好。就个人而言,我会发现以下基于函数的视图比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检索对象实例。