Django中的RESTful api在Django中使用inbult视图,无需创建2个url

Posted

技术标签:

【中文标题】Django中的RESTful api在Django中使用inbult视图,无需创建2个url【英文标题】:RESTful api in Django using inbult view in Django, without creating 2 urls 【发布时间】:2015-11-01 14:01:01 【问题描述】:

我在 Django 中基于函数的视图方面拥有不错的经验,现在我正在尝试使用基于类的视图。虽然我能够解决问题,但我不确定标准,我的意思是如果我做的对或错,你们(Django 开发人员)遵循什么。

关于问题的更多细节在这里-

views.py

from django.views.generic import View

class InvoiceTransaction(View):

    def __init__(self):
        super(InvoiceTransaction, self).__init__()

    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(InvoiceTransaction, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        invoiceid = kwargs.get('invoiceid')
        # here I have invoiceid, which is I'm passing through url paramaeters(see urls.py file)
        # based on invoice, I can decide what type of GET requests it is
        # whether user is asking for a single resource or all resource, right?
        if invoiceid:
             invoice = [Invoice.objects.get(id=invoiceid)]
        else:
             invoice = Invoice.objects.all()

    def post(self, request, *args, **kwargs):
        # some stuff 

urls.py

from django.conf.urls import patterns, url
from invoice import views

urlpatterns = patterns('',
    (r'^invoices/$', views.InvoiceTransaction.as_view()),
    (r'^invoices/(?P<invoiceid>.*)/$', views.InvoiceTransaction.as_view()),
)

我按照这个教程https://realpython.com/blog/python/django-rest-framework-class-based-views/

所以我的问题是我在 urls.py 文件中为单个请求创建了两行(urls)以确定 GET 请求的类型。有没有其他或更好的方法来做到这一点。如何使用视图而不创建 2 个 url 创建一个宁静的 api。

PS:请随意建议对上述代码的改进/更改,因为我是这个东西的新手。可能是我错误地使用了 dispatch 方法,或者真的不需要 init 方法,你建议什么。

【问题讨论】:

【参考方案1】:

试试这个模式,这应该适用于两个网址 -

urlpatterns = patterns('',
    (r'^invoices(/(?P<invoiceid>\d+)),1/$', views.InvoiceTransaction.as_view()),
)

这使得整个 id 块是可选的,但最多只能有一个。

顺便说一句,.* 不太适合 id,最好使用\d+

您可以在 pythex.org 上进行验证。

编辑: ^invoice(/(?P&lt;invoice_type&gt;.*)),1/$

【讨论】:

很好 :) 但是如果你能解释一下这个正则表达式会很棒,因为我对正则表达式不太满意,双小括号和大括号是如何工作的? 外括号是为了使整个块可选或最大 1(注意它后面的,1),这允许invoice/,如果块存在则invoice/10/,因为最大1个可选块被支持invoice/10/5/无效。 ^invoice(/(?P&lt;invoice_type&gt;.*)),1/$ 不起作用?你能建议这有什么问题吗? invoice_type 是一个字符串(在我看来将与预定义的单词匹配) 谁说不工作?我为它添加了另一个屏幕截图。看看吧。 invalid literal for int() with base 10: '' 我在制作这种 url 模式时得到了这个,对于你在答案中写的那个。可能是什么原因。如果我使用 POSTMAN 或其他一些 API 模拟器点击这个 url 它可以工作,但是 django 管理面板没有打开并抛出错误【参考方案2】:

您只需删除第一个模式并从第二个模式中删除结束斜线。 所以,你的 urlpatterns 变成了

urlpatterns = patterns('',
    (r'^invoices/(?P<invoiceid>.*)$', views.InvoiceTransaction.as_view()),
)

这是因为您已经在正则表达式中使用 .* 而不是 .+,您收到的 invoiceid 可以为空。 但是你的正则表达式中的强制结束斜线阻止了这种情况的发生。简单来说,您已经找到了问题的解决方案。

【讨论】:

【参考方案3】:

正如 REST 规定的那样,系统只能用名词和动词来说话。

适用于 RESTful 架构的动词有:

GET
POST
PUT
PATCH
DELETE

还有 2 个 url,RESTful 系统的任何资源表示是:

invoice/$
invoice/(?P<pk>\d+)/$

让我们看看处理没有 pk 的 url 的视图。让我们将此视图称为 InvoiceListCreateView。现在,InvoiceListCreateView 应该只满足 GET 和 POST 请求。它不应该允许PUT, PATCH and DELETE 请求。为什么?

您只能编辑/删除现有对象,并且数据库中的所有现有对象都应该有一个与之关联的 id。所以,当我GETListCreateView 时,我得到了数据库中存在的所有发票的列表。当我 POSTListCreateView 时,我应该能够在数据库的 Invoice 表中插入一个新条目。

现在,附加了 id 的 url。我们称之为RetrieveUpdateDeleteView。顾名思义,视图应该能够执行三个功能,即RETRIEVEUPDATEDELETE。并且所有这些操作都可以在已经存在的对象上执行,这些对象的 id 将出现在 url kwargs 中。

当我 GET RetrieveUpdateDeleteView 时,我必须获取 url kwargs 中提供的 id 的对象。同样,PUTPATCH 应该使用用户发送的数据更新对象。而DELETE 应该从数据库中删除该对象。

这就是我规划REST 架构的方式。

【讨论】:

以上是关于Django中的RESTful api在Django中使用inbult视图,无需创建2个url的主要内容,如果未能解决你的问题,请参考以下文章

Django中CBV和Restful API中的APIView源码分析

Django编写RESTful API:基于类的视图

利用Django实现RESTful API

基于Django RESTframework设计Restful API

Python用Django写restful api接口

Django 和 Restful API