Django使用两种不同的方式实现控制器。你可以使用一个方法来实现每个动作,与Rails做法非常相似,或者你可以为每个控制器动作创建一个类。 Django没有区分new和create方法,资源的创建和空资源的创建发生在同一个控制器中。也没有便捷的方法命名你的视图。视图变量需要从控制器显式的传递,而使用的模板文件也需要显式的设置。
在以上Django的例子中代码数量与RoR相比很明显。Django似乎也注意到这个问题,于是利用继承和mixin开发出了第二种实现控制器的方法。第二种方法称为基于类的视图(class-based views) (注意, Django称这个控制器为view),并且在Django 1.5中引入以提高代码重用。很多常用的动作都存在可被用来继承的类,比如对资源的显示,列表,创建和更新等,这大大简化了代码开发。重复的工作比如指定将被使用的视图文件名称,获取对象并向view传递该对象等工作也会被自动完成。上面相同的例子使用这种方式只有四行代码。
当控制器比较简单时,使用基于类的视图(class-based views)通常是最好的选择,因为代码会变得紧密,具有可读性。但是,取决于你的控制器的不标准(non-standard)程度,可能会需要重写很多函数来得到想要的功能。常遇到的情况就是程序员想向视图传递更多的变量,这时可以重写get_context_data函数来完成。你是不是想按照当前对象(模型实例)的特定的字段来渲染不同的模板?你只好重写render_to_response函数。你想不想改变获得对象的方式(默认是使用主键字段pk)?你只好重写get_object。例如,如果我们想要通过产品名称选择产品而不是id,也要把类似的产品传递给我们的视图,代码就有可能像这样:
视图Rails 视图使用 内置的Ruby 模板系统,它可以让你在你的模板里面编写任意的Ruby代码. 这就意味着它非常强大和快速, 而非常强大的同时就意味着非常大的责任. 你不得不非常小心的不去把表现层同任何其它类型的逻辑混在一起. 这里我需要再次提到涉及一位学生的例子. 一位新同学加入了我们的RoR项目,并且在学习一项新特性. 代码审查的时间到了. 我们首先从控制器开始,第一件令我吃惊的事情是他写的控制器里面代码非常少. 我转而很快去看看他写的视图,看到了大块混着HTML的ruby代码. 诚然,Rails并不会嫌弃缺乏经验的程序员,但我的观点是框架可以帮助开发者避免一些坏的实践. 例如 Django 就有一个非常简洁的 模板语言. 你可以进行if判断以及通过for循环进行迭代,但是没有方法选择没有从控制器传入的对象,因为它并不会执行任意的Python表达式. 这是一个我认为可以敦促开发者方向正确的设计决定. 这能让我们项目中的新手找到组织他们代码的正确方式. 资源: CSS, Javascript 以及 图片Rails 有一个很不错的内置 资源管道. Rails 的资源管道具有对JavaScript和CSS文件进行串联、最小化和压缩的能力. 不仅仅如此,它也还支持诸如 Coffeescript, Sass 和 ERB 等其它语言. Django 对资源的支持同Rails相比就显得相形见绌了,它把要麻烦都丢给了开发者去处理. Django 唯一提供的就是所谓的 静态文件, 这基本上就只是从每个应用程序那里将所有的静态文件集合到一个位置. 有一个叫做 django_compressor 的第三方app提供了一种类似于Rails的资源管道的解决方案. 表单(Forms)网络应用中的表单是用户输入(input)的界面。在Rails中的表单包含在视图中直接使用的帮助方法(method)。
像subject,message这样的输入字段可以在控制器中通过ruby哈希 (类似字典的结构)params来读取,比如params[:subject]和params[:message]。Django通过另一种方式抽象了表单概念。表单封装了字段并包含验证规则。它们看起来像是模型。
Django会将CharField解析为对应HTML元素的文本输入框,将BooleanField解析为单选框。你可以按照自己的意愿使用widget 字段更换为其他输入元素。Django的表单会在控制器中实例化。
Django会自动添加验证信息。默认情况下所有的字段都是必须的,除非特意定义(比如cc_myself)。使用上面的代码片段,如果表单验证失败,带有错误信息的表单会自动重新显示,已经输入的内容也会显示。下面的代码在视图中显示显示了一个表单。
URL 和 RouteRoute 是将特定的URL匹配到指定控制器的工作。Rails建立REST网络服务非常轻松,而route以HTTP的行为(verbs)来表达。
以上的例子显示,向/products/any_id发起的GET请求会自动route到products控制器和show动作(action)。感谢惯例优先原则(convention-over-configuration),对于建立包含所有动作(create,show,index等等)的控制器的这种常见任务,RoR建立了一种快速声明所有常用route的方法,叫做resources。如果你依照Rails的惯例(convention)命名了控制器的方法时这会很方便。
Django不是通过HTTP的行为来决定route。而是使用更复杂的使用正则表达式来匹配URL和对应的控制器。
由于使用了正则表达式,框架会自动使用单纯的验证。请求/products/test/会因匹配不到任何route而返回404,因为test不是正确的数字。不同的哲学思想在这里又一次出现。Django在命名控制器动作方面确实方便一些,以至于Django就没有像Rails的resource那样方便的助手,而且每个route必须显式的定义。这将导致每个控制器需要若干个route规则。 |