Django Rest Framework 3
目录
一、版本
程序也来越大时,可能通过版本不同做不同的处理
没用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)
现在我们来用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(r'test/(?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的更多相关文章
- 使用django rest framework
django 刚接触,想做一些restful api , google了一下,发现有现成的框架.Django REST framework. 对使用做下记录: 安装 从http://django-re ...
- 利用 Django REST framework 编写 RESTful API
利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...
- django rest framework 入门
django rest framework 入门1-序列化 Serialization 分类: Python 2013-01-22 22:24 11528人阅读 评论(0) 收藏 举报 djangop ...
- django rest framework
Django-Rest-Framework 教程: 4. 验证和权限 作者: Desmond Chen, 发布日期: 2014-06-01, 修改日期: 2014-06-02 到目前为止, 我们的AP ...
- django rest framework csrf failed csrf token missing or incorrect
django rest framework csrf failed csrf token missing or incorrect REST_FRAMEWORK = { 'DEFAULT_AUTHEN ...
- Django REST Framework学习——Android使用REST方法访问Diango
本文更应该叫做Android如何模拟浏览器访问Django服务器后台. 环境为: Android通过HttpClient访问服务器,从Django中获取json数据,解析显示在UI界面上. 问题为: ...
- 用Django Rest Framework和AngularJS开始你的项目
Reference: http://blog.csdn.net/seele52/article/details/14105445 译序:虽然本文号称是"hello world式的教程&quo ...
- Django REST framework使用ViewSets的自定义路由实现过程
在Django中使用基于类的视图(ClassView),类中所定义的方法名称与Http的请求方法相对应,才能基于路由将请求分发(dispatch)到ClassView中的方法进行处理,而Django ...
- Django REST FrameWork中文教程2:请求和响应
从这一点开始,我们将真正开始覆盖REST框架的核心.我们来介绍几个基本的构建块. 请求对象REST框架引入了Request扩展常规的对象HttpRequest,并提供更灵活的请求解析.Request对 ...
- Django REST framework 中文教程1:序列化
建立环境 在我们做任何事情之前,我们将使用virtualenv创建一个新的虚拟环境.这将确保我们的包配置与我们正在开展的任何其他项目保持良好的隔离. virtualenv envsource env/ ...
随机推荐
- TCP和Http的区别!(转) 真心有帮助!!!
一.From:http://thisliy.javaeye.com/blog/710122 http://wenku.baidu.com/view/14a30d0102020740be1e9b84.h ...
- Ti CC2540蓝牙模块学习笔记整理
接触CC2540几天,终于有了初步的理解,现将笔记整理如下,只是皮毛,如有错误,还请指正,还有好多没闹明白的地方,以后应该还会继续向里面更新~ 一.整体 1.TI的蓝牙平台支持2种协议栈/应用配置:单 ...
- 《模式 工程化实现及扩展 (设计模式 C#版)》 - 书摘精要
(P3) 面向对象的典型原则可以划分为两类 —— “面向类”的和“面向包”的: “面向类”的,包括:SRP —— 单一职责原则:OCP —— 开放封闭原则:LSP —— 里氏替换原则:DIP —— 依 ...
- New Concept English three (29)
1听力和打字训练: 31w/m 54 typing errors Whether we find a joke funny or not largely depends on were we have ...
- 【html】html笔记综合
基本标签与属性 <html>全部 <body>主体 <h1>标题 <p>段落 <br>空行,一般都会额外添加,并不总是需要自己添加,可以在& ...
- Mybatis为实体类定义别名typeAliases
以新增一个用户为例子,原UserMapper.xml配置如下: <insert id="addUser" parameterType="main.User" ...
- 【前端】XHTML入门笔记
教程/XHTML 模块/XHTML 标准属性/XHTML 事件属性 XHTML 指可扩展超文本标签语言(EXtensible HyperText Markup Language). XHTML 元素必 ...
- python 使用sk_learn 遇到 问题ValueError: Expected 2D array, got 1D array instead:
这里我找到我的问题是: 使用的是一个新的scikit学习版本,它抛出了一个错误,因为在新版本中,所有东西都必须是一个二维矩阵,甚至是一个列或行. 它甚至说:用数组来重塑你的数据.如果您的数据有一个单独 ...
- c# 统计运行时间
long startTime = Environment.TickCount; long endTime = Environment.TickCount; long totalTime = endTi ...
- centos 7 bbr 安装
1. 准备 升级内核需要4.9 以及以上 2. yum 内核升级 a. 添加 ELRepo 源 GPG key rpm --import https://www.elrepo.or ...