Django REST-FrameWork
step1:创建模型
step2:创建一个Serializer类
开始使用Web API的第一件事是提供一种将代码片段实例序列化和反序列化为表示形式(如json)的方法。
使用ModelSerializers:与Django提供的Form类和ModelForm类一样,REST框架包括Serializer类和ModelSerializer类
ModelSerializer类不会做任何特别神奇的事情,它们只是创建序列化器类的快捷方式:
1、一组自动确定的字段。
2、create()和update()方法的简单的实现。
请求和响应
1、请求对象
REST框架引入了Request扩展常规的对象HttpRequest,并提供更灵活的请求解析。Request对象的核心功能是request.data属性,这与request.POST使用Web API 相似但更有用。
request.POST # Only handles form data. Only works for 'POST' method.
request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
2、响应对象
REST框架还引入了一个Response对象,它是一种类型的对象,它TemplateResponse采用未呈现的内容,并使用内容协商来确定正确的内容类型以返回给客户端。
return Response(data) # Renders to content type as requested by the client.
3、状态码
REST框架为每一个状态码更明确的标识符,如HTTP_400_BAD_REQUEST所述的status模块。相对于使用数字标识符更好。
4、包装API视图
REST框架提供了两个可用于编写API视图的包装器。
(1)@api_view用于使用基于功能的视图的装饰器。
(2)继承APIView的基于类的视图工作。
这些包装器提供了一些功能,例如确保您Request在视图中接收实例,并将上下文添加到Response对象,以便可以执行内容协商。
包装器还提供405 Method Not Allowed适当的返回响应等行为,以及处理使用格式不正确的输入ParseError访问时发生的任何异常request.data。
step3、视图
(1)基于函数的视图
我们不再明确地将我们的请求或响应明确绑定到给定的内容类型。 request.data可以处理传入的json请求,但它也可以处理其他格式。类似地,我们使用数据返回响应对象,但允许REST框架将响应呈现给正确的内容类型。
向我们的网址添加可选的格式后缀
为了使我们的响应不再限于单一的内容类型,我们可以为API端点添加对格式后缀的支持。使用格式后缀给我们明确指定给定格式的URL,这意味着我们的API将能够处理诸如http://example.com/api/items/4.json之类的 URL 。
(1)、首先format在两个视图中添加一个关键字参数,就像这样。
(2)、在urls.py稍稍更新文件,format_suffix_patterns除了现有的URL之外还附加一组。
(2)基于类的视图
(3)使用mixin来实现视图
到目前为止,我们使用的创建/检索/更新/删除操作对于我们创建的任何模型支持的API视图将非常相似。 这些常见的行为是在REST框架的mixin类中实现的。
用GenericAPIView创建一个视图,并添加ListModelMixin和CreateModelMixin,到目前为止足够简单。基类提供核心功能,mixin类提供.list()和.create()操作。我们明确的将get和post方法绑定到适当的操作上。
我们再次使用GenericAPIView类来提供核心功能,并在mixin中添加.retrieve(),.update()和.destroy()方法。
(4)使用通用的基于类的视图
step4、权限验证
目前,我们的API对谁可以编辑或删除代码段没有任何限制。我们想要一些更高级的行为:
代码段始终与创建者相关联。
只有身份验证的用户可以创建片段。
只有片段的创建者可以更新或删除它。
未经身份验证的请求应具有完全只读访问权限。
1、将用户信息添加到我们的模型
我们将对我们的Snippet模型类进行一些更改。首先,我们添加几个字段。其中一个字段将用于表示创建代码段的用户。另一个字段将用于存储代码的突出显示的HTML表示。
2、为用户模型添加端点
现在我们有一些用户可以使用,我们最好将这些用户的表示添加到我们的API中。创建一个新的serializer很容易。在serializers.py添加:
因为在User模型上'snippets'是一个反向关系,所以在使用ModelSerializer该类时它不会被默认包含,所以我们需要为它添加一个显式字段。
3、将片段与用户关联
现在,如果我们创建了一个代码片段,那么将无法将创建该代码段的用户与代码段实例相关联。用户不是作为序列化表示的一部分发送的,而是传入请求的属性。
我们处理的方式是覆盖.perform_create()我们的代码片段视图上的方法,这样我们可以修改实例保存的管理方式,并处理传入请求或请求的URL中隐含的任何信息。
在SnippetList视图类中,添加以下方法:
4、更新serializer
现在,这些片段与创建它们的用户相关联,我们更新我们SnippetSerializer来反映这一点。将以下字段添加到序列化器定义中serializers.py:
确保您还添加'owner',到内部Meta类的字段列表。
这个领域正在做一些很有趣的事情。source的那个属性参数控制用于填充的字段,并且可以在对串行化实例的任何属性点。它也可以采用上面显示的点划线,在这种情况下,它将以与Django模板语言一起使用的相似方式遍历给定的属性。
我们添加了字段是类型化ReadOnlyField类,相对于其他类型的字段,如CharField,BooleanField等...类型化ReadOnlyField始终是只读的,并且将用于序列化表示形式,但不会被用于更新模型他们被反序列化的实例。我们也可以CharField(read_only=True)在这里使用。
5、添加视图所需的权限
现在,代码片段与用户相关联,我们希望确保只有经过身份验证的用户才能创建,更新和删除代码段。
REST框架包括许多权限类,我们可以使用它们来限制谁可以访问给定的视图。在这种情况下,我们正在寻找的是IsAuthenticatedOrReadOnly,这将确保经过身份验证的请求获得读写访问权限,未经身份验证的请求将获得只读访问权限。
如果您打开浏览器并导航到目前可浏览的API,那么您将发现无法再创建新的代码段。为了做到这一点,我们需要能够以用户身份登录。
我们可以通过编辑项目级urls.py文件中的URLconf来添加可浏览API使用的登录视图。
r'^api-auth/'模式的一部分实际上可以是您要使用的任何URL。唯一的限制是所包含的URL必须使用'rest_framework'命名空间。
7、对象级权限
我们希望所有的代码片段都可以被任何人看到,但也要确保只有创建代码段的用户才能更新或删除它。要做到这一点,我们将需要创建一个自定义权限。
在片段应用中,创建一个新文件,permissions.py
现在,我们可以通过编辑视图类中的permission_classes属性将该自定义权限添加到我们的代码段实例端点SnippetDetail:
现在,如果再次打开浏览器,您会发现如果您以与创建代码段相同的用户身份登录,“DELETE”和“PUT”操作只会显示在代码段实例端点上。
8、使用API进行身份验证
因为我们现在有一组API的权限,如果我们要编辑任何片段,我们需要验证我们的请求。我们还没有设置任何身份验证类,所以默认值现在被应用,哪些是SessionAuthentication和BasicAuthentication。
当我们通过Web浏览器与API进行交互时,我们可以登录,然后浏览器会话将为请求提供所需的身份验证。
如果我们以编程方式与API交互,我们需要在每个请求上显式提供身份验证凭据。
如果我们尝试创建一个没有验证的代码段,我们会收到一个错误:
step5、ViewSets&Routers
REST框架包括一个处理的抽象ViewSets,它允许开发人员集中精力对API的状态和交互进行建模,并根据常规约定使URL构造自动处理。
ViewSet类是几乎同样的事情View类,但他们提供诸如操作read,或者update,而不是方法处理,如get或put。
一个ViewSet类在最后一刻被绑定到一组方法处理程序,当它被实例化成一组视图时,通常通过使用一个Router类来处理为你定义URL conf的复杂性。
1、我们来看一下我们目前的view,并把它们重构成视图集。
首先,让我们来重构我们UserList和UserDetail View纳入一个单一的UserViewSet。我们可以删除这两个视图,并将其替换为单个类:
在这里,我们使用ReadOnlyModelViewSet该类来自动提供默认的“只读”操作。我们仍然正如我们使用常规视图一样设置queryset和serializer_class属性,但是我们不再需要向两个不同的类提供相同的信息。
接下来我们要更换SnippetList,SnippetDetail和SnippetHighlight视图类。我们可以删除三个视图,并再次替换为单个类。
这一次,我们已经使用了ModelViewSet类来获取完整的默认读写操作。
请注意,我们还使用@detail_route装饰器创建一个名为的自定义操作highlight。此装饰器可用于添加不适合标准create/update/delete样式的任何自定义端点。
默认情况下,使用@detail_route装饰器的自定义操作将响应GET请求。methods如果我们想要一个响应POST请求的动作,我们可以使用该参数。
默认情况下,自定义操作的URL取决于方法名称本身。如果要更改url应该构造的方式,可以将url_path作为decorator的关键字参数。
2、明确地将ViewSets绑定到URL
当我们定义URLConf时,处理程序方法只会被绑定到动作上。看看发生什么事情,让我们首先从ViewSets中明确创建一组视图。
在urls.py文件中,我们将我们的ViewSet类绑定到一组具体的视图中。
请注意,我们如何ViewSet通过将http方法绑定到每个视图所需的操作,从每个类创建多个视图。
现在我们将资源绑定到具体的视图中,我们可以像往常一样使用URL conf注册视图。
3.使用路由器
因为我们使用ViewSet类而不是View类,我们实际上不需要设计自己的URL。将资源连接到视图和网址的约定可以使用Router类自动处理。我们需要做的就是使用路由器注册相应的视图集,然后让它执行其余操作。
这是我们的重新连线的urls.py文件。
与路由器注册视图与提供urlpattern类似。我们包括两个参数:视图的URL前缀和视图本身。
DefaultRouter我们使用的类也会自动为我们创建API根视图,因此我们现在可以api_root从我们的views模块中删除该方法。