【问题标题】:Resource views in DjangoDjango 中的资源视图
【发布时间】:2017-04-05 07:35:54
【问题描述】:

我是第一次使用 Django(我也是 Python 的新手),一段时间以来我一直在努力解决与基于类的视图相关的某个问题。我来自使用 Laravel 的 PHP,在那里你可以拥有所谓的“RESTful 资源控制器”。

对于不熟悉 Laravel 的每个人:这个想法是每个“资源”都有一个控制器(或 Django 中的视图)。这个控制器/视图定义了诸如index()show()create()store()edit()等方法。这些控制器方法的关联url和HTTP方法是GET /photosGET /photos/1、@分别为 987654332@、POST /photosGET /photos/1/edit(例如,如果您正在处理照片)。在 Laravel 的路由中,你只需要声明一行 Route::resource('photos', 'PhotoController') 并且这些 URL 会自动生成。更多信息,我参考Laravel's docs

我真的很喜欢这种模式,我想在 Django 中使用它。

据我了解,Django 并没有开箱即用的东西。 Django 确实有基于类的视图,但它们并不代表资源。相反,您有一个“index()”视图 (PhotoListView),一个“show()”视图 (PhotoDetailView) 等等。

我不确定我应该如何在 Django 中实现这种模式,我什至不确定我想要的是不是一个好主意。

经过研究,我发现了一些可能有用的信息:

http://watchitlater.com/blog/2010/02/django-restful-resources/
https://baxeico.wordpress.com/2014/06/25/put-and-delete-http-requests-with-django-and-jquery/

我不确定第一个链接中的自定义 View 类能实现普通 Django View 无法做到的(普通的 Django View 或多或少做同样的事情,对吧?),我不认为第二个链接正是我想要的(如果我理解正确,这篇文章只是描述了一个中间件,作为 Django 没有将通过 DELETE/PUT 请求发送的数据放入请求中的问题的解决方案)。

基于此,我设计了两种可能的解决方案:

  • 在 URLconf 中使用一行来匹配某个资源的所有 URL,如下所示:

    url(r'^photos/(.*)$', PhotoView.as_view())

    然后,自定义 View 基类的 as_view() 函数将处理诸如 /photos/photos/1/photos/1/edit 等 URL 到正确类方法的路由。缺点是您将路由放在视图中(不是这样做的正确位置),并且您不能以这种方式使用命名模式来引用代码中其他地方的 URL。不过,它最接近它在 Laravel 中的工作方式。

  • 在 URLconf 中为每个 URL 使用单独的行,例如:

    url(r'^photos$', PhotoView.index) url(r'^photos/(\d+)$', PhotoView.show) url(r'^photos/(\d+)/edit$', PhotoView.edit)

    这样做的好处是命名模式照常工作,所有路由都保留在 URLconf 中。但是,我不知道如何在 View 类的实现方面实现这一点(我必须装饰每个方法@classonlymethod,对吧)。

对不起,文字墙,我很高兴听到你关于如何最好地解决这个问题的想法。或者也许我只是疯了,我应该像每个普通的 Django 编码器一样使用基于函数的视图吗?

【问题讨论】:

  • 你见过Django REST Framework吗?
  • @JensAstrup 是的,我(多次)偶然发现了这一点。我不是在构建 API,而是在构建网站/webapp。

标签: python django rest oop django-views


【解决方案1】:

正如 cmets 中的 Jens 所建议的那样。第三方 Django Rest Framework 是我们所拥有的最接近您所描述的 laravel 控制器的东西。要查看的具体项目是viewsets

Django REST 框架允许您将逻辑组合为一组 单个类中的相关视图,称为 ViewSet。在其他框架中 您可能还会发现命名为 something 的概念上相似的实现 比如“资源”或“控制器”。

DRF 的学习曲线非常陡峭。 DRF 还传达了一种印象,即它只适合创建 API。然而,现实是DRF可以用来render HTML and process ordinary HTML forms

REST 框架适用于返回 API 样式的响应,以及 常规 HTML 页面。此外,序列化程序可以用作 HTML 表单 并在模板中呈现。

当然,另一种选择是使用基于类的视图。缺点是它没有在单个类中提供 DRF 视图集的所有功能。但一切都没有丢失。您可以使用CBV Mixins 来混合搭配您需要的功能。

【讨论】:

  • 谢谢。我确实得到的印象是它只适用于 API,而不适用于网站,这就是为什么我没有更多地研究它的原因。 DRF 似乎是我正在寻找的东西,但是我已经编写了一个自定义 View 基类,它可以满足我的需求,并且比 DRF 简单得多(尽管没有那么灵活),并且不需要学习一个全新的框架。完成后我会发布它作为答案。
  • 听起来像是一个计划,但是您不需要从头开始编写视图类,您可以按照提到的方式对 mixin 进行 maix 和匹配,这样您将需要编写很少的代码
  • 太晚了,我已经写好了... ;) 我会检查是否可以使用这些 mixin 重构它。感谢您的提示。
【解决方案2】:

我最终编写了一个基于自定义类的视图,它或多或少是问题中提出的两种解决方案的混合。

一般的想法是我有一个ResourceView,它遵循与Django 的View 类相同的结构(它有as_view()dispatch() 方法)。就像 Django 的 View 一样,as_view() 在内部定义了一个闭包,该闭包返回给 URLconf。这个闭包又依赖dispatch() 将请求分派给正确的(子)方法。为此,它使用'2d map'(dicts 的dict)来确定应该为路由(URL)和HTTP 方法的哪个组合调用哪个方法。与Django的View不同的是,as_view()是在URLconf中调用的,带有指定路由的参数。

我还有一个ResourceRouter,它会自动生成视图对应的URLconf。这种方法在某种程度上受到 DRF 处理方式的启发。

最后但并非最不重要的一点是,我编写了一个装饰器,将模型实例“绑定”到方法,因此模型实例被传递给视图方法,而不是 pk。

代码可以在这里找到:https://gist.github.com/Compizfox/c4e3044755417f59dc33ce97ac8ca07c

【讨论】:

    猜你喜欢
    • 2012-03-12
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    • 2013-07-17
    相关资源
    最近更新 更多