码迷,mamicode.com
首页 > 其他好文 > 详细

Django Rest Framework(3)

时间:2018-02-16 19:10:47      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:response   bcb   没有   默认   messages   手写   www   ever   cts   

一、版本

程序也来越大时,可能通过版本不同做不同的处理

没用rest_framework之前,我们可以通过以下这样的方式去获取。

技术分享图片
 1 class UserView(APIView):
 2     def get(self,request,*args,**kwargs):
 3         version = request.query_params.get(version)
 4         print(version)
 5         if version==v1:
 6             #如果版本是v1
 7             ret = {
 8                 code:111,
 9                 msg:版本一的内容
10             }
11 
12         elif version==v2:
13             # 如果是v2
14             ret = {
15                 code: 112,
16                 msg: 版本二的内容
17             }
18         else:
19             ret = {
20                 code: 0,
21                 msg: 不支持其他版本
22             }
23         return Response(ret)
View Code

现在我们来用rest_framework实现一下,有两种方式

1、基于url的方式

 #基于url传参的形式
     versioning_class = QueryParameterVersioning
    #http://127.0.0.1:8080/api/users/?version=v2
    
#基于url的形式
  versioning_class = URLPathVersioning
  #http://127.0.0.1:8080/api/v1/users/

具体步骤

技术分享图片
1 REST_FRAMEWORK = {
2     DEFAULT_VERSION: v1,  #默认的版本
3     ALLOWED_VERSIONS: [v1,v2],  #允许的版本
4     VERSION_PARAM: version,
5 }
1、配置
技术分享图片
1 from django.conf.urls import url,include
2 from django.contrib import admin
3 
4 
5 urlpatterns = [
6     url(r^admin/, admin.site.urls),
7     url(r^api/(?P<version>[v1|v2]+)/, include(api.urls), name=users-list),
8 ]
urls.py
技术分享图片
1 from api import views
2 urlpatterns = [
3     # url(r‘^users/‘, views.UserView.as_view()),
4     url(r^users/, views.UserView1.as_view()),
5 
6 ]
urls.py
技术分享图片
 1 class UserView1(APIView):
 2     #基于url传参的形式
 3     # versioning_class = QueryParameterVersioning
 4     #http://127.0.0.1:8080/api/users/?version=v2
 5 
 6     #基于url的形式
 7     #http://127.0.0.1:8080/api/v1/users/
 8     versioning_class = URLPathVersioning
 9     def get(self,request,*args,**kwargs):
10         # self.dispatch
11         print(request.version)  #打印的是版本
12         print(request.versioning_scheme)  #打印的是对象
13         if request.version==v2:
14             return Response(我是版本二)
15         elif request.version==v1:
16             return Response(我是版本一)
17         else:
18             return Response(去去去)
views.py

注:在配置的时候

REST_FRAMEWORK = {
                VERSION_PARAM:version,
                DEFAULT_VERSION:v1,
                ALLOWED_VERSIONS:[v1,v2],
                # ‘DEFAULT_VERSIONING_CLASS‘:"rest_framework.versioning.HostNameVersioning" 
          #如果加上这个配置就不用
versioning_class = QueryParameterVersioning这样在指定了,
           DEFAULT_VERSIONING_CLASS:"rest_framework.versioning.URLPathVersioning" }

 

附加:restful提供的反向生成

#http://127.0.0.1:8080/api/v1/users/

技术分享图片
 1 #urls.py 
 2 #分发路由
 3 urlpatterns = [
 4     url(r^admin/, admin.site.urls),
 5     url(r^api/(?P<version>[v1|v2]+)/, include(api.urls)),
 6 ]
 7 
 8 #api.urls.py
 9 urlpatterns = [
10     url(r^users/, views.UserView1.as_view(), name=users-list),
11 ]
12 
13 #views.py 
14 导入类
15 from rest_framework.reverse import reverse
16 url = request.versioning_scheme.reverse(viewname=users-list,request=request)
17         print(url)
restfoamework反向解析

我们自己用django实现的,当前版本不一样的时候可以用这种方式

 from django.urls import reverse
        url = reverse(viewname=users-list,kwargs={version:v2}) #指定的是v2就是v2,当你路径中输入v1的时候还是v2的路径
        print(url) #/api/v2/users/

2、基于子域名传参

技术分享图片
 1 #分发url
 2             urlpatterns = [
 3                 #url(r‘^admin/‘, admin.site.urls),
 4                 url(r^api/, include(api.urls)),
 5             ]
 6 
 7             urlpatterns = [
 8                 url(r^users/, views.UsersView.as_view(),name=u),
 9             ]
10             
11             
12             class UsersView(APIView):
13                 
14                 def get(self,request,*args,**kwargs):
15                     self.dispatch
16                     print(request.version) # QueryParameterVersioning().detemiin_version()
17                     print(request.versioning_scheme) # QueryParameterVersioning()
18 
19             
20             REST_FRAMEWORK = {
21                 VERSION_PARAM:version,
22                 DEFAULT_VERSION:v1,
23                 ALLOWED_VERSIONS:[v1,v2],
24                 DEFAULT_VERSIONING_CLASS:"rest_framework.versioning.HostNameVersioning"
25             }
26             
27             # C:\Windows\System32\drivers\etc
28             # vim /etc/hosts
29             127.0.0.1    v1.luffy.com
30             127.0.0.1    v2.luffy.com
31             
32             #配置ALLOWED_HOSTS = [‘*‘]
基于子域名传参

 

 如果遇到这样的错误

技术分享图片

这是由于没有允许,解决办法,在settings里面配置一下

ALLOWED_HOSTS = [*]

 

二、解析器:reqest.data取值的时候才执行

对请求的数据进行解析:是针对请求体进行解析的。表示服务器可以解析的数据格式的种类

django中的发送请求

#如果是这样的格式发送的数据,在POST里面有值
Content-Type: application/url-encoding.....
    request.body
    request.POST
    
#如果是发送的json的格式,在POST里面是没有值的,在body里面有值,可通过decode,然后loads取值        
Content-Type: application/json.....
    request.body
    request.POST

 

为了这种情况下每次都要decode,loads,显得麻烦,所以才有的解析器。弥补了django的缺点

技术分享图片
 1 客户端:
 2             Content-Type: application/json
 3             {"name":"alex","age":123}
 4         
 5         服务端接收:
 6             读取客户端发送的Content-Type的值 application/json
 7             
 8             parser_classes = [JSONParser,FormParser]  #表示服务器可以解析的数据格式的种类
 9             media_type_list = [application/json,application/x-www-form-urlencoded]
10         
11             如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
12             如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据
13         
14         
15         配置:
16             单视图:
17             class UsersView(APIView):
18                 parser_classes = [JSONParser,]
19                 
20             全局配置:
21                 REST_FRAMEWORK = {
22                     VERSION_PARAM:version,
23                     DEFAULT_VERSION:v1,
24                     ALLOWED_VERSIONS:[v1,v2],
25                     # ‘DEFAULT_VERSIONING_CLASS‘:"rest_framework.versioning.HostNameVersioning"
26                     DEFAULT_VERSIONING_CLASS:"rest_framework.versioning.URLPathVersioning",
27                     DEFAULT_PARSER_CLASSES:[
28                         rest_framework.parsers.JSONParser,
29                         rest_framework.parsers.FormParser,
30                     ]
31                 }
32                 
33                 class UserView(APIView):
34                     def get(self,request,*args,**kwargs):
35                         return Response(ok)
36                     def post(self,request,*args,**kwargs):
37                         print(request.data)  #以后取值就在这里面去取值
38                         return Response(...)
具体讲解

传上传文件

技术分享图片
1 from django.conf.urls import url, include
2 from web.views import TestView
3 
4 urlpatterns = [
5     url(rtest/(?P<filename>[^/]+), TestView.as_view(), name=test),
6 ]
urls.py
技术分享图片
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from rest_framework.views import APIView
 4 from rest_framework.response import Response
 5 from rest_framework.request import Request
 6 from rest_framework.parsers import FileUploadParser
 7 
 8 
 9 class TestView(APIView):
10     parser_classes = [FileUploadParser, ]
11 
12     def post(self, request, filename, *args, **kwargs):
13         print(filename)
14         print(request.content_type)
15 
16         # 获取请求的值,并使用对应的JSONParser进行处理
17         print(request.data)
18         # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
19         print(request.POST)
20         print(request.FILES)
21         return Response(POST请求,响应内容)
22 
23     def put(self, request, *args, **kwargs):
24         return Response(PUT请求,响应内容)
views.py
技术分享图片
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
 9     <input type="text" name="user" />
10     <input type="file" name="img">
11 
12     <input type="submit" value="提交">
13 
14 </form>
15 </body>
16 </html>
upload.html

全局使用

技术分享图片
1 REST_FRAMEWORK = {
2     DEFAULT_PARSER_CLASSES:[
3         rest_framework.parsers.JSONParser
4         rest_framework.parsers.FormParser
5         rest_framework.parsers.MultiPartParser
6     ]
7 
8 }
settings.py

三、序列化

序列化用于对用户请求数据进行验证和数据进行序列化(为了解决queryset序列化问题)。

那什么是序列化呢?序列化就是把对象转换成字符串,反序列化就是把字符串转换成对象

models.py

from django.db import models

# Create your models here.
class Group(models.Model):
    title = models.CharField(max_length=32)
    mu = models.ForeignKey(to=Menu,default=1)

class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    group = models.ForeignKey(to="Group")

    roles = models.ManyToManyField(to="Role")
class Menu(models.Model):
    name = models.CharField(max_length=21)

class Role(models.Model):
    name = models.CharField(max_length=32)

1、基本操作

技术分享图片
 1 from django.shortcuts import render,HttpResponse
 2 from rest_framework.views import APIView
 3 from rest_framework.response import Response
 4 from rest_framework.versioning import BaseVersioning
 5 from rest_framework.versioning import QueryParameterVersioning  #获取version的值
 6 from rest_framework.versioning import URLPathVersioning #支持版本
 7 from rest_framework.versioning import HostNameVersioning
 8 from rest_framework.parsers import JSONParser  #解析器
 9 from rest_framework import serializers
10 from app03 import models
11 class UsersSerializer(serializers.Serializer):
12     name = serializers.CharField()  #字段名字
13     pwd = serializers.CharField()
14 
15 class UserView(APIView):
16     def get(self,request,*args,**kwargs):
17         # 方式一实现
18         # user_list = models.UserInfo.objects.values(‘name‘,‘pwd‘,‘group__mu‘,‘group__title‘)
19         # print(type(user_list))
20         # return Response(user_list)
21 
22         # 方式二之多对象
23         # user_list = models.UserInfo.objects.all()  #直接这样查会报错,借助他提供的系列化
24         # ser = UsersSerializer(instance=user_list,many=True) #可允许多个
25         # # print(type(ser))  #<class ‘rest_framework.serializers.ListSerializer‘>
26         # print(ser.data)  #返回的是一个有序字典
27 
28         #方式三之单对象
29         user = models.UserInfo.objects.all().first()
30         ser = UsersSerializer(instance=user,many=False)
31 
32         return Response(ser.data)
views.py

2、跨表

技术分享图片

 x1 = serializers.CharField(source=group.mu.name) 

   如果你想跨表拿你任何需要的数据,都可以用上面的这种操作,内部做判断,如果可用内部就加括号调用了

技术分享图片
 1 from rest_framework.views import APIView
 2 from rest_framework.response import Response
 3 from rest_framework import serializers
 4 from app03 import models
 5 class UsersSerializer(serializers.Serializer):
 6     name = serializers.CharField()  #字段名字
 7     pwd = serializers.CharField()
 8     # group = serializers.CharField()  #会显示对象
 9     # group_id = serializers.CharField()  #会显示id
10     x1 = serializers.CharField(source=group.mu.name)
11     roles = serializers.CharField(source=roles.all) #多对多关系的这样查出的是queryset对象
12 
13 class UserView2(APIView):
14     ‘‘‘跨表操作‘‘‘
15     def get(self,request,*args,**kwargs):
16 
17         user = models.UserInfo.objects.all()
18         ser = UsersSerializer(instance=user,many=True)
19 
20         return Response(ser.data)
Views.py

3、复杂序列化

解决方案一:

技术分享图片
 1 class MyCharField(serializers.CharField):
 2 
 3     def to_representation(self, value): ##打印的是所有的数据
 4         data_list = []
 5         for row in value:
 6             data_list.append(row.name)
 7         return data_list
 8 
 9 class UsersSerializer(serializers.Serializer):
10     name = serializers.CharField() # obj.name
11     pwd = serializers.CharField()  # obj.pwd
12     group_id = serializers.CharField() # obj.group_id
13     xxxx = serializers.CharField(source="group.title") # obj.group.title
14     x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
15     # x2 = serializers.CharField(source="roles.all") #  多对多关系的这样查出的是queryset对象
16     x2 = MyCharField(source="roles.all") # obj.mu.name
Views.py

解决方案二:

技术分享图片
 1 class MyCharField(serializers.CharField):
 2     def to_representation(self, value):
 3         return {id:value.pk, name:value.name}
 4 
 5 class UsersSerializer(serializers.Serializer):
 6     name = serializers.CharField() # obj.name
 7     pwd = serializers.CharField()  # obj.pwd
 8     group_id = serializers.CharField() # obj.group_id
 9     xxxx = serializers.CharField(source="group.title") # obj.group.title
10     x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
11     # x2 = serializers.CharField(source="roles.all") # obj.mu.name
12     x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name
Views.py

解决方案三(推荐使用)

技术分享图片
 1 class UsersSerializer(serializers.Serializer):
 2     name = serializers.CharField() # obj.name
 3     pwd = serializers.CharField()  # obj.pwd
 4     group_id = serializers.CharField() # obj.group_id
 5     xxxx = serializers.CharField(source="group.title") # obj.group.title
 6     x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
 7     # x2 = serializers.CharField(source="roles.all") # obj.mu.name
 8     # x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name
 9     x2 = serializers.SerializerMethodField()
10 
11     def get_x2(self,obj):  #get_字段名
12         print(obj)   ##UserInfo object
13         obj.roles.all()
14         role_list = obj.roles.filter(id__gt=1)
15         data_list = []
16         for row in role_list:
17             data_list.append({pk:row.pk,name:row.name})
18         return data_list
19     
Views.py

4、基于Model

技术分享图片
 1 class UsersSerializer(serializers.ModelSerializer):
 2 x1 = serializers.CharField(source=name)
 3 group = serializers.HyperlinkedIdentityField(view_name=detail)
 4 class Meta:
 5     
 6     model = models.UserInfo
 7     # fields = "__all__"
 8     fields = [name,pwd,group,x1]  #自定义字段的时候注意要指定source,scource里面的数据必须是数据库有的数据
 9     depth = 1 #表示深度
10 
11 
12 class UsersView(APIView):
13     def get(self,request,*args,**kwargs):
14         self.dispatch
15         # 方式一:
16         # user_list = models.UserInfo.objects.all().values(‘name‘,‘pwd‘,‘group__id‘,"group__title")
17         # return Response(user_list)
18 
19         # 方式二之多对象
20         user_list = models.UserInfo.objects.all()
21         # [obj1,obj2,obj3]
22         ser = UsersSerializer(instance=user_list,many=True)
23         return Response(ser.data)
Views.py

5、生成URL

技术分享图片
 1 class UsersSerializer(serializers.ModelSerializer):  #
 2     group = serializers.HyperlinkedIdentityField(view_name=detail)
 3     class Meta:
 4         model = models.UserInfo
 5         fields = "__all__"
 6         fields = [name, pwd,group]
 7         depth = 1
 8 
 9 
10 class UsersView(APIView):
11     def get(self,request,*args,**kwargs):
12         self.dispatch
13         # 方式一:
14         # user_list = models.UserInfo.objects.all().values(‘name‘,‘pwd‘,‘group__id‘,"group__title")
15         # return Response(user_list)
16 
17         # 方式二之多对象
18         user_list = models.UserInfo.objects.all()
19         # [obj1,obj2,obj3]
20         ser = UsersSerializer(instance=user_list,many=True,context={request:request})
21         return Response(ser.data)
views.py
from django.conf.urls import url,include
from django.contrib import admin
from app03 import views
urlpatterns = [

    url(r^users4/, views.UserView4.as_view(), name=xxx), #吧users4的group的值反向生成users5的url
    url(r^users5/(?P<pk>.*), views.UserView5.as_view(), name=detail),  #必须叫pk
    # url(r‘^users4/(?P<pk>.*)‘, views.UserView4.as_view(), name=‘detail‘),
]

6、全局生成URL

技术分享图片
 1 class UsersSerializer(serializers.HyperlinkedModelSerializer): #继承他自动生成
 2     class Meta:
 3         model = models.UserInfo
 4         fields = "__all__"
 5 
 6         # fields = [‘id‘,‘name‘,‘pwd‘]  
 7 
 8 class UsersView(APIView):
 9     def get(self,request,*args,**kwargs):
10         self.dispatch
11         # 方式一:
12         # user_list = models.UserInfo.objects.all().values(‘name‘,‘pwd‘,‘group__id‘,"group__title")
13         # return Response(user_list)
14 
15         # 方式二之多对象
16         user_list = models.UserInfo.objects.all()
17         # [obj1,obj2,obj3]
18         ser = UsersSerializer(instance=user_list,many=True,context={request:request})
19         return Response(ser.data)
views.py

技术分享图片

技术分享图片

四、请求数据验证:

a、自己手写

技术分享图片
 1 class PasswordValidator(object):
 2     def __init__(self, base):
 3         self.base = base
 4 
 5     def __call__(self, value):
 6         if value != self.base:
 7             message = 用户输入的值必须是 %s. % self.base
 8             raise serializers.ValidationError(message)
 9 
10     def set_context(self, serializer_field):
11         """
12         This hook is called by the serializer instance,
13         prior to the validation call being made.
14         """
15         # 执行验证之前调用,serializer_fields是当前字段对象
16         pass
17 
18 class UsersSerializer(serializers.Serializer):
19         name = serializers.CharField(min_length=6)
20         pwd = serializers.CharField(error_messages={required: 密码不能为空}, validators=[PasswordValidator(666)])
views.py

b、基于model

技术分享图片
 1 class PasswordValidator(object):
 2     def __init__(self, base):
 3         self.base = base
 4 
 5     def __call__(self, value):
 6         if value != self.base:
 7             message = 用户输入的值必须是 %s. % self.base
 8             raise serializers.ValidationError(message)
 9 
10     def set_context(self, serializer_field):
11         """
12         This hook is called by the serializer instance,
13         prior to the validation call being made.
14         """
15         # 执行验证之前调用,serializer_fields是当前字段对象
16         pass
17 
18 class UsersSerializer(serializers.ModelSerializer):
19     class Meta:
20         model = models.UserInfo
21         fields = "__all__"
22         #自定义验证规则
23         extra_kwargs = {
24             name: {min_length: 6},
25             pwd: {validators: [PasswordValidator(666), ]}
26         }
views.py

使用

技术分享图片
 1 class UsersView(APIView):
 2     def get(self,request,*args,**kwargs):
 3         self.dispatch
 4         # 方式一:
 5         # user_list = models.UserInfo.objects.all().values(‘name‘,‘pwd‘,‘group__id‘,"group__title")
 6         # return Response(user_list)
 7 
 8         # 方式二之多对象
 9         user_list = models.UserInfo.objects.all()
10         # [obj1,obj2,obj3]
11         ser = UsersSerializer(instance=user_list,many=True,context={request:request})
12         return Response(ser.data)
13 
14     def post(self,request,*args,**kwargs):
15         ser = UsersSerializer(data=request.data)
16         if ser.is_valid():
17             print(ser.validated_data)
18         else:
19             print(ser.errors)
20         return Response(...)
viewS.py

钩子函数

def validate_字段(self,validated_value):
       raise ValidationError(detail=xxxxxx)
       return validated_value
                        

 

Django Rest Framework(3)

标签:response   bcb   没有   默认   messages   手写   www   ever   cts   

原文地址:https://www.cnblogs.com/huchong/p/8450355.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!