在django.shortcuts.render和django.views.generic.TemplateView之间选择

时间:2018-08-26 08:07:59

标签: python django

我已经阅读了几个Django教程。

我注意到基于静态HTML模板文件生成动态Web内容,有2种方法

  • django.conf.urls.url中使用url.py。指向将调用django.shortcuts.render的命名函数。
  • django.urls.path中使用url.py。指向一个从django.views.generic.TemplateView继承的命名类。

两种方法都能产生相同的结果。

我想知道,如何确定给定情况下使用哪种方式?

1 个答案:

答案 0 :(得分:2)

基于的基于类的视图(CBV)和基于基于功能的视图(FBV)都可以做相同的事情:始终可以将CBV转换为FBV在特定视图在功能上等效的意义上,反之亦然。

赞成基于基于类的视图(CBV)

CBV通常用于抽象常见逻辑。例如,在模板视图中,您无需调用render(..),这对我们来说是隐式完成的:我们只需要提供模板的名称即可。此外,如果以后发现某个“代码流”存在问题,可以很容易地在特定视图中对其进行修补,因此所有视图都可以立即修复,而如果错误位于FBV中,则我们需要修补所有FBV。

它还将视图拆分为一组 reuseable 组件:例如,DetailView包含一个组件,用于计算要渲染的对象,一个组件可以添加额外的数据上下文,以及执行实际渲染的方法。如果以后要允许在该视图上发出POST请求,则已经有那些组件可用。

通过使用(多重)继承等面向对象的技术,

CBV还可以轻松地创建 ad hoc 控制流。 > mixins :无需定义特定的控制流,可以定义一个mixin,然后将其混合到应该更改控制流的视图中。

这也使得对视图进行子类化的操作变得容易:如果您有一个显示 all 记录的视图,则需要两个工作流,才能将该视图子类化为在新视图中对记录进行分页。如果以后再更改旧的记录视图,那么此更改也会立即对所有子类产生影响(但是有时可能会产生不希望的副作用)。

从某种意义上说,不同的HTTP请求的处理也更整洁(视图可以具有get(..)post(..)patch(..)等方法),而在基于函数的视图中,通常使用if request.method == 'POST'处理。通常,这会导致以下事实:处理非POST请求(例如PATCH)就像是GET一样,而建议您返回“ 405 Method Not Allowed”错误。可以通过基于函数的视图来完美地解决此问题,但是它需要做一些额外的工作,因此经常被忽略。

最后,Django有许多通用的View子类,可以处理常见的情况,例如呈现对象列表,创建或更新模型对象的新实例等。(几乎)CBV涵盖了很多用例,因此只需要对该特定视图进行子类化,然后填写详细信息(模板名称,对模型的引用等)。这还会导致更多的声明性编程:说出您想要的 ,而不是您想要的 how 。例如,Django的ListView支持分页。

赞成基于功能的视图(FBV)

但是,基于功能的视图会显示控制流,而在基于类的视图中,这是隐藏的,因此是 Django魔术。无法看到控制流会使 debug 视图变得更加困难,因为所有类型的操作都是在“幕后”完成的,并且可能由于某种视图的某些特殊性,就会发生错误。

基于功能的视图也往往更易于实现:您获得一个request对象以及一些(URL)参数,并且需要将其转换为HTTP响应。您不必为我需要获取哪些对象辩解:您只需在函数中以临时样式获取对象(当然,您也可以可以在CBV中,但这并不是CBV背后的想法。

最后,Django还提供了大量的函数修饰符,例如@login_required(CBV有对应的部分)。通常,对函数装饰器的含义进行推理要比对视图的子类化的含义更容易:子类化可以对视图的 all 产生影响。此外,具有多重继承的子类化并不总是那么简单:Python使用方法解析顺序(MRO)来确定super().some_method()是什么,但这可能会导致一些棘手的副作用,而这些副作用可能不会View的实现者或视图混合器已经预见到了。

Django向基于类的视图转变

但是,当您查看Django的开发时,您会看到从基于函数的视图向基于类的视图的转变:例如,在中,基于login的基于函数的视图删除。 中引入了CBV副本(LoginView)。但是,这并不意味着Django开发人员必须将所有内容都编写为CBV:Django通常涵盖相当通用的视图,因此在这种情况下使用CBV更有意义。