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请求返回:

 

posted @ 2018-04-28 11:08  Paco_Pig  阅读(138)  评论(0)    收藏  举报