目录

一、版本

二、解析器

三、序列化

四、请求数据验证


一、版本

回到顶部

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

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

 class UserView(APIView):
def get(self,request,*args,**kwargs):
version = request.query_params.get('version')
print(version)
if version=='v1':
#如果版本是v1
ret = {
'code':111,
'msg':'版本一的内容'
} elif version=='v2':
# 如果是v2
ret = {
'code': 112,
'msg': '版本二的内容'
}
else:
ret = {
'code': 0,
'msg': '不支持其他版本'
}
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/

具体步骤

 REST_FRAMEWORK = {
'DEFAULT_VERSION': 'v1', #默认的版本
'ALLOWED_VERSIONS': ['v1','v2'], #允许的版本
'VERSION_PARAM': 'version',
}

1、配置

 from django.conf.urls import url,include
from django.contrib import admin urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/(?P<version>[v1|v2]+)/', include('api.urls'), name='users-list'),
]

urls.py

 from api import views
urlpatterns = [
# url(r'^users/', views.UserView.as_view()),
url(r'^users/', views.UserView1.as_view()), ]

urls.py

 class UserView1(APIView):
#基于url传参的形式
# versioning_class = QueryParameterVersioning
#http://127.0.0.1:8080/api/users/?version=v2 #基于url的形式
#http://127.0.0.1:8080/api/v1/users/
versioning_class = URLPathVersioning
def get(self,request,*args,**kwargs):
# self.dispatch
print(request.version) #打印的是版本
print(request.versioning_scheme) #打印的是对象
if request.version=='v2':
return Response('我是版本二')
elif request.version=='v1':
return Response('我是版本一')
else:
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/

 #urls.py
#分发路由
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/(?P<version>[v1|v2]+)/', include('api.urls')),
] #api.urls.py
urlpatterns = [
url(r'^users/', views.UserView1.as_view(), name='users-list'),
] #views.py
导入类
from rest_framework.reverse import reverse
url = request.versioning_scheme.reverse(viewname='users-list',request=request)
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、基于子域名传参

 #分发url
urlpatterns = [
#url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls')),
] urlpatterns = [
url(r'^users/', views.UsersView.as_view(),name='u'),
] class UsersView(APIView): def get(self,request,*args,**kwargs):
self.dispatch
print(request.version) # QueryParameterVersioning().detemiin_version()
print(request.versioning_scheme) # QueryParameterVersioning() REST_FRAMEWORK = {
'VERSION_PARAM':'version',
'DEFAULT_VERSION':'v1',
'ALLOWED_VERSIONS':['v1','v2'],
'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"
} # C:\Windows\System32\drivers\etc
# vim /etc/hosts
127.0.0.1 v1.luffy.com
127.0.0.1 v2.luffy.com #配置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的缺点

 客户端:
Content-Type: application/json
'{"name":"alex","age":123}' 服务端接收:
读取客户端发送的Content-Type的值 application/json parser_classes = [JSONParser,FormParser] #表示服务器可以解析的数据格式的种类
media_type_list = ['application/json','application/x-www-form-urlencoded'] 如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据 配置:
单视图:
class UsersView(APIView):
parser_classes = [JSONParser,] 全局配置:
REST_FRAMEWORK = {
'VERSION_PARAM':'version',
'DEFAULT_VERSION':'v1',
'ALLOWED_VERSIONS':['v1','v2'],
# 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"
'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
]
} class UserView(APIView):
def get(self,request,*args,**kwargs):
return Response('ok')
def post(self,request,*args,**kwargs):
print(request.data) #以后取值就在这里面去取值
return Response('...')

具体讲解

传上传文件

 from django.conf.urls import url, include
from web.views import TestView urlpatterns = [
url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
]

urls.py

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FileUploadParser class TestView(APIView):
parser_classes = [FileUploadParser, ] def post(self, request, filename, *args, **kwargs):
print(filename)
print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
print(request.data)
# application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES)
return Response('POST请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

views.py

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
<input type="text" name="user" />
<input type="file" name="img"> <input type="submit" value="提交"> </form>
</body>
</html>

upload.html

全局使用

 REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser'
'rest_framework.parsers.FormParser'
'rest_framework.parsers.MultiPartParser'
] }

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、基本操作

 from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import BaseVersioning
from rest_framework.versioning import QueryParameterVersioning #获取version的值
from rest_framework.versioning import URLPathVersioning #支持版本
from rest_framework.versioning import HostNameVersioning
from rest_framework.parsers import JSONParser #解析器
from rest_framework import serializers
from app03 import models
class UsersSerializer(serializers.Serializer):
name = serializers.CharField() #字段名字
pwd = serializers.CharField() class UserView(APIView):
def get(self,request,*args,**kwargs):
# 方式一实现
# user_list = models.UserInfo.objects.values('name','pwd','group__mu','group__title')
# print(type(user_list))
# return Response(user_list) # 方式二之多对象
# user_list = models.UserInfo.objects.all() #直接这样查会报错,借助他提供的系列化
# ser = UsersSerializer(instance=user_list,many=True) #可允许多个
# # print(type(ser)) #<class 'rest_framework.serializers.ListSerializer'>
# print(ser.data) #返回的是一个有序字典 #方式三之单对象
user = models.UserInfo.objects.all().first()
ser = UsersSerializer(instance=user,many=False) return Response(ser.data)

views.py

2、跨表

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

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

 from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from app03 import models
class UsersSerializer(serializers.Serializer):
name = serializers.CharField() #字段名字
pwd = serializers.CharField()
# group = serializers.CharField() #会显示对象
# group_id = serializers.CharField() #会显示id
x1 = serializers.CharField(source='group.mu.name')
roles = serializers.CharField(source='roles.all') #多对多关系的这样查出的是queryset对象 class UserView2(APIView):
'''跨表操作'''
def get(self,request,*args,**kwargs): user = models.UserInfo.objects.all()
ser = UsersSerializer(instance=user,many=True) return Response(ser.data)

Views.py

3、复杂序列化

解决方案一:

 class MyCharField(serializers.CharField):

     def to_representation(self, value): ##打印的是所有的数据
data_list = []
for row in value:
data_list.append(row.name)
return data_list class UsersSerializer(serializers.Serializer):
name = serializers.CharField() # obj.name
pwd = serializers.CharField() # obj.pwd
group_id = serializers.CharField() # obj.group_id
xxxx = serializers.CharField(source="group.title") # obj.group.title
x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
# x2 = serializers.CharField(source="roles.all") # 多对多关系的这样查出的是queryset对象
x2 = MyCharField(source="roles.all") # obj.mu.name

Views.py

解决方案二:

 class MyCharField(serializers.CharField):
def to_representation(self, value):
return {'id':value.pk, 'name':value.name} class UsersSerializer(serializers.Serializer):
name = serializers.CharField() # obj.name
pwd = serializers.CharField() # obj.pwd
group_id = serializers.CharField() # obj.group_id
xxxx = serializers.CharField(source="group.title") # obj.group.title
x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
# x2 = serializers.CharField(source="roles.all") # obj.mu.name
x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name

Views.py

解决方案三(推荐使用)

 class UsersSerializer(serializers.Serializer):
name = serializers.CharField() # obj.name
pwd = serializers.CharField() # obj.pwd
group_id = serializers.CharField() # obj.group_id
xxxx = serializers.CharField(source="group.title") # obj.group.title
x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
# x2 = serializers.CharField(source="roles.all") # obj.mu.name
# x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name
x2 = serializers.SerializerMethodField() def get_x2(self,obj): #get_字段名
print(obj) ##UserInfo object
obj.roles.all()
role_list = obj.roles.filter(id__gt=1)
data_list = []
for row in role_list:
data_list.append({'pk':row.pk,'name':row.name})
return data_list

Views.py

4、基于Model

 class UsersSerializer(serializers.ModelSerializer):
x1 = serializers.CharField(source='name')
group = serializers.HyperlinkedIdentityField(view_name='detail')
class Meta: model = models.UserInfo
# fields = "__all__"
fields = ['name','pwd','group','x1'] #自定义字段的时候注意要指定source,scource里面的数据必须是数据库有的数据
depth = 1 #表示深度 class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 方式一:
# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
# return Response(user_list) # 方式二之多对象
user_list = models.UserInfo.objects.all()
# [obj1,obj2,obj3]
ser = UsersSerializer(instance=user_list,many=True)
return Response(ser.data)

Views.py

5、生成URL

 class UsersSerializer(serializers.ModelSerializer):  #
group = serializers.HyperlinkedIdentityField(view_name='detail')
class Meta:
model = models.UserInfo
fields = "__all__"
fields = ['name', 'pwd','group']
depth = 1 class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 方式一:
# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
# return Response(user_list) # 方式二之多对象
user_list = models.UserInfo.objects.all()
# [obj1,obj2,obj3]
ser = UsersSerializer(instance=user_list,many=True,context={'request':request})
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

 class UsersSerializer(serializers.HyperlinkedModelSerializer): #继承他自动生成
class Meta:
model = models.UserInfo
fields = "__all__" # fields = ['id','name','pwd'] class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 方式一:
# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
# return Response(user_list) # 方式二之多对象
user_list = models.UserInfo.objects.all()
# [obj1,obj2,obj3]
ser = UsersSerializer(instance=user_list,many=True,context={'request':request})
return Response(ser.data)

views.py

四、请求数据验证:

回到顶部

a、自己手写

 class PasswordValidator(object):
def __init__(self, base):
self.base = base def __call__(self, value):
if value != self.base:
message = '用户输入的值必须是 %s.' % self.base
raise serializers.ValidationError(message) def set_context(self, serializer_field):
"""
This hook is called by the serializer instance,
prior to the validation call being made.
"""
# 执行验证之前调用,serializer_fields是当前字段对象
pass class UsersSerializer(serializers.Serializer):
name = serializers.CharField(min_length=6)
pwd = serializers.CharField(error_messages={'required': '密码不能为空'}, validators=[PasswordValidator('')])

views.py

b、基于model

 class PasswordValidator(object):
def __init__(self, base):
self.base = base def __call__(self, value):
if value != self.base:
message = '用户输入的值必须是 %s.' % self.base
raise serializers.ValidationError(message) def set_context(self, serializer_field):
"""
This hook is called by the serializer instance,
prior to the validation call being made.
"""
# 执行验证之前调用,serializer_fields是当前字段对象
pass class UsersSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = "__all__"
#自定义验证规则
extra_kwargs = {
'name': {'min_length': 6},
'pwd': {'validators': [PasswordValidator(666), ]}
}

views.py

使用

 class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 方式一:
# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
# return Response(user_list) # 方式二之多对象
user_list = models.UserInfo.objects.all()
# [obj1,obj2,obj3]
ser = UsersSerializer(instance=user_list,many=True,context={'request':request})
return Response(ser.data) def post(self,request,*args,**kwargs):
ser = UsersSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data)
else:
print(ser.errors)
return Response('...')

viewS.py

钩子函数

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

Restful Framework (三)的更多相关文章

  1. 4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍

    4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍 天涯明月笙 关注 2018.02.20 19:23* 字数 762 阅读 135 ...

  2. 3- vue django restful framework 打造生鲜超市 - model设计和资源导入

    3- vue django restful framework 打造生鲜超市 - model设计和资源导入 使用Python3.6与Django2.0.2(Django-rest-framework) ...

  3. django restful framework 一对多方向更新数据库

    目录 django restful framework 序列化 一 . 数据模型: models 二. 序列化: serializers 三, 视图: views 四, 路由: urls 五. 测试 ...

  4. Springboot & Mybatis 构建restful 服务三

    Springboot & Mybatis 构建restful 服务三 1 前置条件 成功执行完Springboot & Mybatis 构建restful 服务二 2 restful ...

  5. 在django restful framework中设置django model的property

    众所周知,在django的model中,可以某些字段设置@property和setter deleter getter,这样就可以在存入数据的时候进行一些操作,具体原理请参见廖雪峰大神的博客https ...

  6. Restful framework【第三篇】序列化组件

    基本使用 -序列化 -对象,转成json格式 用drf的序列化组件 -定义一个类继承class BookSerializer(serializers.Serializer): -写字段,如果不指定so ...

  7. Restful Framework 初识

    目录 一.什么是RESTful 二.什么是API 三.RESTful API规范 四.基于Django实现API 五.基于Django Rest Framework框架实现 一. 什么是RESTful ...

  8. django restful framework教程大全

    一. 什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角 ...

  9. Restful framework【第六篇】认证组件

    基本用法 -认证功能 1 写一个类,继承BaseAuthentication 2 def authenticate(self,request) ,记住传request对象 -如果验证通过,返回None ...

随机推荐

  1. SRM12 T2夏令营(分治优化DP+主席树 (已更新NKlogN)/ 线段树优化DP)

     先写出朴素的DP方程f[i][j]=f[k][j-1]+h[k+1][i] {k<i}(h表示[k+1,j]有几个不同的数)  显然时间空间复杂度都无法承受   仔细想想可以发现对于一个点 i ...

  2. Javascript计算世界完全对称日

    今天是 2011-11-02 日,微博啊.G+啊什么的都传是世界完全对称日,还说是多少年一遇的.下面写个 JavaScript 小程序,看看是否真的N年一遇.计算范围在公元2000年到3000年. 名 ...

  3. 洛谷P3065 [USACO12DEC]第一!First!(Trie树+拓扑排序)

    P3065 [USACO12DEC]第一!First! 题目链接:https://www.luogu.org/problemnew/show/P3065 题目描述 Bessie一直在研究字符串.她发现 ...

  4. 【题解】Casting Spells LA 4975 UVa 1470 双倍回文 SDOI 2011 BZOJ 2342 Manacher

    首先要吐槽LRJ,书上给的算法标签是“有难度,需要结合其他数据结构”,学完Manacher才发现几乎一裸题 题目的意思是问原串中有多少个wwRwwR这样的子串,其中wR表示w的反串 比较容易看出来,w ...

  5. 51Nod 1094 和为k的连续区间 | 水

    Input示例 6 10 1 2 3 4 5 6 Output示例 1 4 #include "cstdio" #include "algorithm" #in ...

  6. consul windows安装

    Consul 是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,由 HashiCorp 公司用 Go 语言开发, 基于 Mozilla Public License 2.0 的协议进行开 ...

  7. 【Foreign】画方框 [主席树]

    画方框 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output 输出一行一个整数,表示 CD 最多可能画了几个方框. Sam ...

  8. PHP正则 贪婪匹配与非贪婪匹配

    $str = ".abcdeabcde"; preg_match('/a.+?e/', $str, $match); print_r($match); Array ( [0] =& ...

  9. [bzoj4567][Scoi2016]背单词-Trie+贪心+模型转化

    Brief Description 给你N个互不相同的字符串,记\(S_i\)为第i个字符串,现在要求你指定N个串的出现顺序,我们用\(V_i\)表示第i个字符串是第几个出现的,则V为1到N的一个排列 ...

  10. js 基本类型&引用类型

    1.基本的数据类型有:undefined,boolean,number,string,null.基本类型的访问是按值访问的,就是说你可以操作保存在变量中的实际的值 基本类型的比较是值的比较.用==比较 ...