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/ ...
随机推荐
- wireshark捕获到的TCP包图示
wireshark抓到的包与对应的协议层如下图所示: wireshark捕获到的TCP包中的每个字段如下图所示:
- IOS-RunTime(刨根问底)
方法调用 让我们看一下方法调用在运行时的过程(参照前文类在runtime中的表示) 如果用实例对象调用实例方法,会到实例的isa指针指向的对象(也就是类对象)操作.如果调用的是类方法,就会到类对象的i ...
- node 一站式 学习 教程
还是比较全面的, 包括了 : monogoDB的安装 使用 , 各种插件, 中间件的介绍, 路由的介绍, 各种数据库框架的介绍, 测试介绍; 掌握后应该可以开发一个中型的程序, 大型程序因为有性能的 ...
- Could not find a valid gem 'rails' (>= 0), here is why
很长一段时间之前 Ruby Rails入门--windows下搭建Ruby Rails Web开发环境 ,由于后来将Ruby的安装文件从 C 盘移动到了 D 盘,也修改了 Path 环境变量,ruby ...
- HAWQ取代传统数仓实践(七)——维度表技术之维度子集
有些需求不需要最细节的数据.例如更想要某个月的销售汇总,而不是某天的数据.再比如相对于全部的销售数据,可能对某些特定状态的数据更感兴趣等.此时事实数据需要关联到特定的维度,这些特定维度包含在从细节维度 ...
- 剑指Offer面试题:1.实现单例模式
一 题目:实现单例模式Singleton 题目:设计一个类,我们只能生产该类的一个实例. 只能生成一个实例的类是实现了Singleton(单例)模式的类型.由于设计模式在面向对象程序设计中起着举足轻重 ...
- python 爬虫的一些使用技巧
1.最基本的抓站 import urllib2 content = urllib2.urlopen('http://XXXX').read() -2.使用代理服务器这在某些情况下比较有用,比如IP被封 ...
- 把color转成image的方法
- (UIImage*)createImageWithColor:(UIColor*) color { CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); ...
- ACM学习历程—51NOD 1412 AVL树的种类(递推)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1770 这是这次BSG白山极客挑战赛的B题.设p(i, j)表示节点个数为 ...
- 十二、python沉淀之路--内置函数
1.abs函数,求绝对值. a = abs(-3) print(a) 返回:3 2.all函数:判断是否是可迭代对象. 官方解释:Return True if bool(x) is True for ...