3.版本 解析器 序列化
表结构新添加了1张表和2个字段,用于实现多对多关联和键
from django.db import models
class UserGroup(models.Model):
title = models.CharField(max_length=32)
class UserInfo(models.Model):
user_type_choices = (
(1,'普通用户'),
(2,'VIP'),
(3,'SVIP'),
)
user_type = models.IntegerField(choices=user_type_choices)
username = models.CharField(max_length=32,unique=True)
password = models.CharField(max_length=64)
group = models.ForeignKey("UserGroup")
roles = models.ManyToManyField("Role")
class UserToken(models.Model):
user = models.OneToOneField(to='UserInfo')
token = models.CharField(max_length=64)
class Role(models.Model):
title = models.CharField(max_length=32)
1.全局配置: vim settings.py(加在最后一行)
REST_FRAMEWORK = {
"DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.QueryParameterVersioning",
"DEFAULT_VERSION":'v1', #默认版本
"ALLOWED_VERSIONS":['v1','v2'], #允许的版本只有v1和v2
"VERSION_PARAM":'version',
"DEFAULT_PARSER_CLASSES":['rest_framework.parsers.JSONParser','rest_framework.parsers.FormParser'] #配置解析器,这里配置上,其他的每个视图就都有了
}
备注:其中DEFAULT_VERSIONING_CLASS不是列表,所以不能写多个,常用的有:URLPathVersioning和QueryParameterVersioning
URLPathVersioning代表:http://127.0.0.1/user/?version=v1 这种形式
QueryParameterVersioning代表:http://127.0.0.1/v1/user/ 这种形式
2.vim urls.py(项目的URLS.py)
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls')),
]
3.vim api.urls.py(应用的URLS.py)
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view(),name='uuu'),
url(r'^(?P<version>[v1|v2]+)/django/$', views.DjangoView.as_view(),name='ddd'),
url(r'^(?P<version>[v1|v2]+)/parser/$', views.ParserView.as_view()),
url(r'^(?P<version>[v1|v2]+)/roles/$', views.RolesView.as_view()),
url(r'^(?P<version>[v1|v2]+)/userinfo/$', views.UserInfoView.as_view()),
url(r'^(?P<version>[v1|v2]+)/group/(?P<xxx>\d+)$', views.GroupView.as_view(),name='gp'),
url(r'^(?P<version>[v1|v2]+)/usergroup/$', views.UserGroupView.as_view(),name='gp'),
]
4.vim view.py
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning
from django.urls import reverse
from api import models
import json
#版本
class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 获取版本
print(request.version)
# 获取处理版本的对象
print(request.versioning_scheme)
# 反向生成URL(rest framework)
u1 = request.versioning_scheme.reverse(viewname='uuu',request=request)
print(u1)
# 反向生成URL
u2 = reverse(viewname='uuu',kwargs={'version':2})
print(u2)
return HttpResponse('用户列表')
class DjangoView(APIView):
def post(self,request,*args,**kwargs):
print(type(request._request))
from django.core.handlers.wsgi import WSGIRequest
return HttpResponse('POST和Body')
#解析器
from rest_framework.parsers import JSONParser,FormParser
class ParserView(APIView):
# parser_classes = [JSONParser,FormParser,]
"""
JSONParser:表示只能解析content-type:application/json头
FormParser:表示只能解析content-type:application/x-www-form-urlencoded头
"""
def post(self,request,*args,**kwargs):
"""
允许用户发送JSON格式数据
a. content-type: application/json
b. {'name':'alex',age:18}
:param request:
:param args:
:param kwargs:
:return:
"""
"""
1. 获取用户请求
2. 获取用户请求体
3. 根据用户请求头 和 parser_classes = [JSONParser,FormParser,] 中支持的请求头进行比较
4. JSONParser对象去请求体
5. request.data
"""
print(request.data)
return HttpResponse('ParserView')
#序列化(简单roles表)
from rest_framework import serializers
class RolesSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField()
class RolesView(APIView):
def get(self,request,*args,**kwargs):
# 方式一:
# roles = models.Role.objects.all().values('id','title')
# roles = list(roles)
# ret = json.dumps(roles,ensure_ascii=False) ensure-ascii代表显示中文,默认是True
# 方式二:对于 [obj,obj,obj,] 返回的数据{"id":1,"title":"护士"},{"id":2,"title":"律师"}。。。。。。。
# roles = models.Role.objects.all()
# ser = RolesSerializer(instance=roles,many=True)
# ret = json.dumps(ser.data, ensure_ascii=False)
#many=False代表是单独的,返回的数据{"id":1,"title":"护士"}
role = models.Role.objects.all().first()
ser = RolesSerializer(instance=role, many=False)
# ser.data 已经是转换完成的结果
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
#序列化(复杂userinfo表)
# class UserInfoSerializer(serializers.Serializer):
# xxxxx = serializers.CharField(source="user_type") #没写source,数据库的字段需一一对应,写了source,列明就可以随便写了,这样选择编号 {xxxxx:“1”}
# oooo = serializers.CharField(source="get_user_type_display") # row.get_user_type_display() 这样就可以显示数据库里面定义的选择类型中文 {ooooo:“普通用户”}
# username = serializers.CharField()
# password = serializers.CharField()
# gp = serializers.CharField(source="group.title")
# # rls = serializers.CharField(source="roles.all")
# rls = serializers.SerializerMethodField() # 自定义显示,下面要定义一个函数 如果是manytomany就应该通过这个方法来实现
#
# def get_rls(self,row): #必须这样写,get开头,加自定义显示的名字,这样才能跟上面的rls关联起来
#
# role_obj_list = row.roles.all()
#
# ret = []
# for item in role_obj_list:
# ret.append({'id':item.id,'title':item.title})
# return ret
class MyField(serializers.CharField):
def to_representation(self, value):
print(value)
return "xxxxx"
# class UserInfoSerializer(serializers.ModelSerializer):
# oooo = serializers.CharField(source="get_user_type_display") # row.user_type
# rls = serializers.SerializerMethodField() # 自定义显示
# x1 = MyField(source='username')
#
# class Meta:
# model = models.UserInfo
# # fields = "__all__"
# fields = ['id','username','password','oooo','rls','group','x1']
#
# def get_rls(self, row):
# role_obj_list = row.roles.all()
#
# ret = []
# for item in role_obj_list:
# ret.append({'id':item.id,'title':item.title})
# return ret
class UserInfoSerializer(serializers.ModelSerializer):
group = serializers.HyperlinkedIdentityField(view_name='gp',lookup_field='group_id',lookup_url_kwarg='xxx') #这样可以让group返回的是url
class Meta:
model = models.UserInfo
# fields = "__all__"
fields = ['id','username','password','group','roles']
depth = 0 # 0 ~ 10
group字段如果要返回url就是像上面那样写,很少这样用,知道就可以了
最终我们通过url访问,得到如下:
depth=0请求返回:
depth=1请求返回:
class UserInfoView(APIView):
def get(self,request,*args,**kwargs):
users = models.UserInfo.objects.all()
# 对象, Serializer类处理; self.to_representation
# QuerySet,ListSerializer类处理; self.to_representation
ser = UserInfoSerializer(instance=users,many=True,context={'request': request})
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
#这是查看组的详细
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserGroup
fields = "__all__"
class GroupView(APIView):
def get(self,request,*args,**kwargs):
pk = kwargs.get('xxx')
obj = models.UserGroup.objects.filter(pk=pk).first()
ser = GroupSerializer(instance=obj,many=False)
ret = json.dumps(ser.data,ensure_ascii=False)
return HttpResponse(ret)
# #################### 验证 ############################
class XXValidator(object):
def __init__(self, base):
self.base = base
def __call__(self, value):
if not value.startswith(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 UserGroupSerializer(serializers.Serializer):
title = serializers.CharField(error_messages={'required':'标题不能为空'},validators=[XXValidator('老男人'),])
def validate_title(self, value): #value是""老男人sdf""
from rest_framework import exceptions
raise exceptions.ValidationError('看你不顺眼') #要么返回老男人sdf,要么报异常二选一
return value #返回老男人sdf
class UserGroupView(APIView):
def post(self,request,*args,**kwargs):
ser = UserGroupSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data['title'])
else:
print(ser.errors)
return HttpResponse('提交数据')
这样可以让group返回的是url

最终我们通过url访问,得到如下:

depth=0请求返回:

depth=1请求返回:


浙公网安备 33010602011771号