rest api框架

django-icetea的Python项目详细描述


#django icetea是一个构建在[django]之上(https://www.djangoproject.com/)的包,提供了创建restapi的抽象。

它受到了[django活塞](https://bitbucket.org/jespern/django-piston/wiki/home)和[pisto]架构的影响。n-perfect)(https://github.com/smartpr/piston-perfect)。

注册在[pypi]中(http://pypi.python.org/pypi/django icetea/),因此安装它就像运行一样简单:


但是,我建议使用github的最新版本。主分支总是稳定的。

,以防服务器出错。默认值为``true`。

*``icetea_display_errors``:使用``true``,在发生
服务器错误时返回格式正确的错误消息。它要求"debug=true"。默认值为"true"。

使用[epydoc](http://epydoc.sourceforge.net/)解析它并从中生成
文档。例如,为了创建一个带有
文档的*html*页面,``cd``进入*django icetea*文件夹,并发出:



打开文件*index.html*,获取整个代码
文档。


它努力使事情清晰明了,
在幕后没有任何不必要的魔力。

选项需要预先定义。

例如,尽管*http*是一种
应用程序协议,但它主要用于与web
浏览器的交互。当应用于更一般的请求/响应方案时,存在协议本身不指示正确行为的
场景。
因此,我主要将*http*视为请求和响应的传输方式
。它不知道业务逻辑,因此它缺少将特定于应用程序的语义或错误映射到*http
响应*的方法。

*http*协议没有真正指定
行为的一个具体情况是:

>;假设我们需要创建一个模型实例;我们向
>;api发出一个*post*请求,我们期望得到一个响应,该响应将指示*如果
>;资源已被CR已创建,如果是,则返回资源。
>;服务器首先需要验证已接收的数据。如果数据
>;无效,则API应返回"400错误请求"响应。如果数据
>;有效,但在创建数据库时失败,我们该怎么办?是否返回"400错误请求"?没办法。这将混淆用户,并指示
>;提供的数据无效。请求已成功验证,
>;因此情况并非如此,是否返回成功的响应"`200 OK`"、
>;和空数据?我选择后者。这表明数据确实有效,但无法创建资源。

这是我在这个项目中的主要目标之一。如果不同的应用程序由于需要不同的语义,
*django icetea*的代码可以很容易地修改以支持它们。

此外,遵循[最小惊奇原则](http://en.wikipedia.org/wiki/principle廑of廑u last廑u)这是一般的*python*和*django*特别鼓励,我试图遵循*django*用户熟悉的一般行为。例如,``modelhandler``类的``validation``方法(在``handlers.py``模块中)。它
清理数据,创建模型实例(不将它们提交到
数据库),并使用模型的"完全清除"方法验证它们。一旦
完成,我们确信我们处理的是完全有效的模型
实例,我们可以安全地将其写入数据库。这意味着我们不需要手动执行所有这些步骤,因为它们是由
*django icetea*提供的。这正是django*modelform*验证的工作原理,也是大多数django*开发人员习惯于做的事情。
方法已更改(rest api而不是forms),但过程仍然是
相同的。


提供现成的crud
功能。

*``basehandler`:用于公开未映射到模型上的数据。大多数
功能都需要手动编写。

资源
通常由url标识。例如,`/resource/<;id>;/``上的*get/put/delete*请求是一个
单数请求。

``复数请求`:影响(检索或修改)一组资源(通常是客户机有权查看的子集或所有资源)的请求。它可以是复数get、复数put、
或复数delete。

``bulk request`:请求体中有一个数据数组的请求。它只对*post*请求有意义,目的是在一个请求中创建多个实例。对于批量post请求,
没有推荐的行为或语义,因此我们定义了自己的语义,以确保
功能是可预测的并且最有意义。更多详细信息请参见[批量发布请求]部分(https://github.com/stargazer/django icetea批量发布请求)。


例如,
以下格式的get请求`/resource/<;id>;/``请求具有``id=<;id>;```的资源。

这对于安全相关的检查非常重要,它主要控制
请求是否是复数的,并且如果已显式地允许这样的请求
.

传入请求

传入请求的"内容类型"标题应为
"应用程序/json"。这是目前
*django icetea*识别的唯一请求正文格式。

\django icetea*的传出响应可以是以下格式之一:

*`application/json`
*`text/xml`
*`text/html`
*`aapplication/vnd.ms excel`

默认值为``application/json`。
请注意,在输出``json`,或``xml`的情况下,很容易在响应中序列化
数据结构。但是,在"html"和
特别是"xls"格式的情况下,应该(可能)对输出
发射器应用特定于应用程序的语义。



*``403 forbidden``:客户端未通过身份验证
*``405 method not allowed``:请求方法是在不支持该方法的源
*``410 gone`:资源不可用
*``422 unprocessableentity``:请求有效,但由于资源的语义而无法处理(例如,对属于已验证客户端的资源的*delete*请求)。如果特定资源的字段*x*具有特定值,我们可能会选择不允许删除该资源。在这种情况下,我们用一个*422 unprocessableentity*响应来响应)。


有自己的测试套件,可以在"tests.py"模块中找到。此模块定义基本测试类,用于测试"django icetea"本身,也可用于测试任何api实现。


\csrf tokens

[csrf漏洞](http://www.squarefree.com/securitytips/web developers.html\csrf)。
django的*csrfviewmiddleware*在将表单发送到web浏览器之前,使用
*post方法*在每个表单中插入一个*csrf标记*作为隐藏字段。对于来自web浏览器的每个后续
*post request*,相同的中间件都会检查令牌,以确保
它包含预期值。如果没有返回*403禁止的*响应,

但是,由于*django icetea*是一个api并且不使用表单,
csrf令牌没有多大意义。因此默认情况下,*django icetea*视图是
*csrf豁免*,这意味着它们不需要csrf令牌。

假设我们有一个名为"foo"的django应用程序,它有一个模型"foo model"。

例如,``model handler``类,定义
对应的模型在该处理程序中的表示方式(哪些字段应该
公开),但也定义了它嵌套在其他处理程序的响应中的情况。


foo/handlers.py

todo:example with a basehandler

业务的实现者
逻辑

`` python
从foo.models导入foo model
从icetea.handlers导入modelhandler


类foomhandler(modelhandler):
身份验证=true
模型=foomodel

读取=true
创建=true

允许的输出字段=(
'id',
'field1',
'field2',







>允许在字段中使用的单位字段=(
'field1',
'field2',

````















我们需要创建资源(相当于django视图),这些资源将启动
api请求的服务



``python
.url.defaults导入t*
从foo.handlers导入foo handler
从icetea.resource导入resource


foo handler=resource(foohandler)

url(r'^foo/$',foo handler),
url(r'^foo/(?p<;id>;\d+/$',foo\u handler),

````



分别是"post"、"put"和"delete"请求。

方法,例如:

``python
def read(self,request,*args,**kwargs):
pass
````


>然后启用相应的操作,默认功能由定义。

默认值为"false"。有关详细信息,请参见[注释]部分(https://github.com/stargazer/django icetea notes)。

要求"create=true"。

放置请求,这意味着在一个请求中更新多个
资源。这是一个潜在的灾难性操作,对于
这个原因应该被明确允许。默认值为"false"。

要求"update=true"。

启用时,您应该预期会出现"400个错误请求"响应,并在响应的正文中列出列表。

探索。这是一个潜在的灾难性操作,因此应该明确允许。默认值为"false"。

要求"delete=true"。

启用时,您应该预料到"422个无法处理的实体"的响应,并在响应的正文中列出一个列表。

或者。如果"true",则选择器为"field"。如果"false",则不会选择字段。默认值为"true"。


如果"false",则不能执行订单类型
选择。默认值为"false"。
顺序逻辑应该在处理程序的"order_data"方法中实现。


``切片''.如果"false",则不可能进行切片。默认值为"false"。
切片符号遵循python的*切片符号*,即"start:stop:step"。

使用*django
身份验证*。默认值为``false`。




在"model handler"的情况下,它表示模型字段。

在"basehandler"的情况下,它只有在处理程序返回字典或字典列表时才有意义,并且它表示允许处理程序输出的字典键。

请求最终将输出的lds是
此参数的函数,以及由
字段中的"字段"指示的请求级别字段选择


oming请求正文。在``model handler``
类的情况下,不允许使用主键或相关键。















``filter name`````````过滤器




F型过滤操作"对"。`` filter
name``定义用于对当前请求应用筛选的querystring参数。`` filter_operation``对应于django lookup
过滤器,它将应用于请求的结果数据。

它可以是字符串,也可以是返回a
字符串。默认值为"file.xls`

\notes


by*fake*我指的不是实际的物理模型字段,而是我们希望在api处理程序的输出中包含的额外信息。这样做非常简单。

然后定义类方法
`` compute_fake廑fields(self,field)```,它应该返回假字段的值。

例如:

`` python
假字段=('num廑tweets','num廑retweets',)

def廑compute廑fake廑fields(self,field):
如果字段='num廑tweets':

return self.tweets.count()

elif field=='转发次数':
return retweet.objects.filter(tweet\u in=self.tweets.all()).count()
`````
emitter``类调用方法````compute\u fake`fields`',
德勒"`field`"参数是要计算的字段名
。因此``计算假字段``方法应该能够计算出``假字段``元组中的所有字段名。

从这一点开始,api处理程序可以将这些字段视为普通的模型字段。
这意味着,它们可以包含在元组``允许输出字段`,
`排除字段中。ested```,等等,这取决于您想如何对待它们。


\bulk post requests

*bulk post request*指试图创建多个资源的单个"post"请求。"rest"或"http"的规范没有为此类请求指定
任何标准行为,而是不鼓励使用,因为
语义不好。


例如,api如何在
请求体中的某个数据对象上发出错误信号?或者,当请求主体中的所有数据
对象都有效时,它如何表示数据库错误?

我选择了以下行为:

*请求正文中的任何错误,都将返回一个"坏请求"响应。
例如,当请求正文中的数据引用django模型时,如果
即使其中一个模型未能验证,响应也将为"400坏请求"。响应体将包含一个列表,其中包含所有无法验证的对象。每个对象都应该有一个"index"参数,该参数
指定请求体参数的零bazed索引,无法对其进行
验证。

(类似地,对于单个实例的"post"请求,如果请求体不包含有效数据,则返回"bad request`


*如果请求正文有效,则响应为"ok",其正文包含所有成功添加的模型实例的列表。如果未能创建一个模型
实例(例如,由于数据库错误),
尽管它包含有效数据,但它将不属于响应
数据的一部分。

(类似于对单个实例的POST请求,返回一个"确定"响应,并且请求正文。如果未能创建模型
实例,尽管它是有效的,但我们返回一个"ok"响应,响应体中有"null"。

在我看来,这是最直观的行为。但是我认为这一切都取决于每个应用程序的需求,以及使用api的客户机。
所以可以随意修改现有的行为。

可以通过在handler类中设置
``bulk\u create=true``来启用它们。


\元类魔术在本小节中,术语"操作"是指"读取"、"创建"、"更新"、"删除"中的一个。当处理程序类设置"读取=真"时,它基本上对系统说:

>;我想继承标准的"read"功能。请提供给我。

显然,要将布尔属性"read"转换为方法,需要在
please中使用一些魔法。

元类的工作方式是,当初始化一个类时,python
解释器扫描它自己的成员属性,然后*运行
元类的代码。在本例中,元类所做的是删除所有用"true"定义的
操作,例如"read=true",以便
为它们留出继承空间。元类在类
初始化时运行,而[python
mro](http://www.python.org/getit/releases/2.3/mro/)在运行时运行。

作为
方法,它需要将它们提供为"read=true"。这样,它的元类
将删除这些属性,并为从中继承
的类创建"空间",以继承这些操作定义的行为。当然,继承自基处理程序的
处理程序首先需要显式地允许
操作,以防它们希望继承其功能。

因此,在生成处理程序时查看它的方式:

>;设置"read=true"意味着处理程序本身和继承自它的处理程序将继承"read"功能,前提是它们允许这样做。
>;
>;设置"read=false"或根本不设置"read"属性将阻止``阅读``处理程序及其继承的处理程序的功能。


*成功:
*状态代码:200
*响应体:字典
*错误:
*状态代码:403
*响应体:空
*状态代码:405
*响应体:空
*状态码:410
*响应体:空

*复数
*成功:
*状态码:200
*响应体:列表
*错误:
*状态码:403
*响应体:empty
*状态码:405
*响应体:empty

*post
*指单个资源(请求体中的字典)
*成功:
*状态码:200
*响应体dy:dictionary
*响应体:``null`(当数据库故障阻止数据对象写入数据库时发生)
*错误:
*状态代码:400
*响应体:dictionary
*状态码:403
*响应体:empty
*状态码:405
*响应体:empty
*状态码:422
*响应体:dictionary
*批量(请求正文中的列表)
*成功
*状态代码:200
*响应正文:列表
*错误
*状态代码:400
*响应正文:列表(列表项是字典)。每个
字典都应该有一个"index"参数,该参数定义了
从零开始的请求体实例索引无效)
*状态代码:403
*响应体:空
*状态代码:405
*响应体:空
*状态代码:422
*响应体:列表(列表项是字典)。每个
字典都应该有一个"index"参数,该参数定义导致错误的请求正文实例的从零开始的索引


*put
*singular
*successful
*statusS代码:200
*响应体:dictionary
*错误
*状态代码:400
*响应体:dictionary
*状态代码:403
*响应体:空
*状态代码:405
*响应体:empty
*状态码:410
*响应体:empty
*状态码:422
*响应体:dictionary
*复数
*成功
*状态码:200
*响应体:list
*错误
*状态代码:400
*响应体:list(列表项是字典)。每个
字典都应提供一个"id"参数,该参数定义了无效的(模型)实例的"id"。
*状态代码:403
*响应体:空
*状态代码:405
*响应体:空
*状态代码:422
*响应体:列表(列表项是字典)。每个
字典都应提供一个"id"参数,该参数定义导致错误的(模型)实例的"id"


*删除
*单数
*成功
*状态代码:200
*响应体:字典
*错误
*状态代码:403
*响应体:空
*状态代码:405
*响应体:空
*状态代码:410
*response body:empty
*状态码:422
*响应体:dictionary
*复数
*成功
*状态码:200
*响应体:list
*错误
*状态码:403
*响应体:empty
*状态代码:405
*响应体:empty
*状态代码:422
*响应体:list(列表项是字典)。每个
字典都应提供一个"id"参数,该参数定义了导致错误的(模型)实例的"id"。

e*在字典的情况下,*multiple*在
列表的情况下)将包含以下键:

*``errors`:它将是一个由{``field``:[``error``]}对组成的字典,在可能的情况下,
或一个描述错误的字符串列表。
*``type`:error type

在错误列表的情况下,每个项都将包含键"index"或
``id``,这将指定哪个请求正文项或哪个数据模型实例导致相应的错误。



``python

{
"错误":{
"文本":[
"此字段不能为空"
]
},
"类型":"验证错误"
}

```

`` python
批量post请求的错误响应
[
{
"index":0,
"errors":{
"gender":[
"value u'bi"不是有效的选择。"
],
"email":[
"invalid em"邮件"
]
},
"类型":"验证错误"
},
{
"索引":3,
"错误":{
"邮政编码":[
"无效邮政编码"
]
"类型":"验证错误"
}
}
]

```

``python
``多个删除请求的错误响应
[
{
"id":2,
"errors":[
"instance cannot delete"
],
"type":"unprocessable entity error"
},
{
"id":4,
"errors":[
"instance cannot be delete"
],
"type":"unprocessable entity error"
}
]

````

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
如何从java中链接到数组的数组中删除值。jar文件?   性能记录屏幕Java磁盘速度   java Elastic APM Tomcat zip文件或JAR清单丢失   java无法在eclipse控制台上打印结果   java如何在Android中解析json对象?   java如何更改边缘根类型   java根据一些规则替换EditText中的字母   java项目反应器:是否有类似Nosideeffect finally的方法(不是sideeffect方法doFinally)   java连接Cassandra节点和spark   开源Java作业调度器:远程处理、负载平衡、故障切换、依赖DAG?   使用矢量汇编程序(Java)在Spark中设置输入和输出时出现问题   swing如何在Java中为文本字段创建右键单击菜单?   java查找最近的邻居/纬度和经度   java计算完成的数独板的行和列