我已经阅读了几个Django教程。
我注意到基于静态HTML模板文件生成动态Web内容,有2种方法
django.conf.urls.url
中使用url.py
。指向将调用django.shortcuts.render
的命名函数。django.urls.path
中使用url.py
。指向一个从django.views.generic.TemplateView
继承的命名类。两种方法都能产生相同的结果。
我想知道,如何确定给定情况下使用哪种方式?
答案 0 :(得分:2)
基于的基于类的视图(CBV)和基于基于功能的视图(FBV)都可以做相同的事情:始终可以将CBV转换为FBV在特定视图在功能上等效的意义上,反之亦然。
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
支持分页。
但是,基于功能的视图会显示控制流,而在基于类的视图中,这是隐藏的,因此是 Django魔术。无法看到控制流会使 debug 视图变得更加困难,因为所有类型的操作都是在“幕后”完成的,并且可能由于某种视图的某些特殊性,就会发生错误。
基于功能的视图也往往更易于实现:您获得一个request
对象以及一些(URL)参数,并且需要将其转换为HTTP响应。您不必为我需要获取哪些对象辩解:您只需在函数中以临时样式获取对象(当然,您也可以可以在CBV中,但这并不是CBV背后的想法。
最后,Django还提供了大量的函数修饰符,例如@login_required
(CBV有对应的部分)。通常,对函数装饰器的含义进行推理要比对视图的子类化的含义更容易:子类化可以对视图的 all 产生影响。此外,具有多重继承的子类化并不总是那么简单:Python使用方法解析顺序(MRO)来确定super().some_method()
是什么,但这可能会导致一些棘手的副作用,而这些副作用可能不会View
的实现者或视图混合器已经预见到了。
但是,当您查看Django的开发时,您会看到从基于函数的视图向基于类的视图的转变:例如,在django-2.1中,基于login
的基于函数的视图删除。 django-1.11中引入了CBV副本(LoginView
)。但是,这并不意味着Django开发人员必须将所有内容都编写为CBV:Django通常涵盖相当通用的视图,因此在这种情况下使用CBV更有意义。