restful——序列化组件

一 、Django自带序列化组件

serializers(把对象序列化成json字符串)

from django.core import serializers

 

from django.core import serializers
def test(request):
    book_list = Book.objects.all()    
    ret = serializers.serialize("json", book_list)
    return HttpResponse(ret)

 

二 、rest-framework序列化之Serializer

models:

from django.db import models

# Create your models here.


class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")
    def __str__(self):
        return self.title

class Publish(models.Model):
    name=models.CharField(max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    def __str__(self):
        return self.name

views:

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializers


from rest_framework import serializers

class BookSerializers(serializers.Serializer):
    title=serializers.CharField(max_length=32)
    price=serializers.IntegerField()
    pub_date=serializers.DateField()
    publish=serializers.CharField(source="publish.name")
    #authors=serializers.CharField(source="authors.all")
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        temp=[]
        for author in obj.authors.all():
            temp.append(author.name)
        return temp
  #此处可以继续用author的Serializers,
  # def get_authors(self,obj):
    #     ret=obj.authors.all()
    #     ss=AuthorSerializer(ret,many=True)
    #     return ss.data

class BookViewSet(APIView):

    def get(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        # 序列化方式1:
        # from django.forms.models import model_to_dict
        # import json
        # data=[]
        # for obj in book_list:
        #     data.append(model_to_dict(obj))
        # print(data)
        # return HttpResponse("ok")

        # 序列化方式2:
        # data=serializers.serialize("json",book_list)
        # return HttpResponse(data)

        # 序列化方式3:
        bs=BookSerializers(book_list,many=True)     #many=True代表有多条数据,如果只有一条数据,many=False
        return Response(bs.data)
     # 序列化方式4: 
      # ret=models.Book.objects.all().values('nid','title')
     # dd=list(ret)
        # return HttpResponse(json.dumps(dd))
View Code

注意:

source 如果是字段,会显示字段,如果是方法,会执行方法,不用加括号(authors=serializers.CharField(source='authors.all'))

如在模型中定义一个方法,直接可以在在source指定执行

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)


#视图
ret=models.UserInfo.objects.filter(pk=1).first()
aa=ret.get_user_type_display()

#serializer
xx=serializers.CharField(source='get_user_type_display')

 choices的用法:  详情

 

三 rest-framework序列化之ModelSerializer

官方: 网关链接

models 中:

import datetime
from django.db import models
class ExecuteUser(models.Model): uid = models.AutoField(primary_key=True) name = models.CharField(max_length=64, null=True, blank=True) class TestInfo(models.Model): """ 测试记录详情 """ uid = models.AutoField(primary_key=True) request_id = models.CharField(max_length=64, null=True, blank=True)# 关系 sub_index = models.ForeignKey(to='self', to_field='uid', on_delete=models.SET_NULL, blank=True, null=True,# 执行人 execute_user = models.ForeignKey(to="ExecuteUser", to_field='uid', on_delete=models.SET_NULL, blank=True, null=True, related_name="execute_user", db_column='execute_user')

 

views 中:

class GetTestData(GenericAPIView):
    def get(self, request):
        params = request.query_params
        # 获取所有数据
        _data = TestInfo.objects.all()
        resp_info = my_serializer.TestInfoSerializers(instance=_data, many=True)
        resp = []
        for i in resp_info.data:
            _dict = dict(i)
            resp.append(_dict)
        return JsonResponse(resp, safe=False)

 

my_serializers中:

设置queryset后, read_only=True可以不设置, 就默认读写权限
# -*- coding: utf-8 -*-

from rest_framework import serializers
from . import models


class TestInfoSerializers(serializers.ModelSerializer):
    """
    cbt任务测试序列化组件 
    """
    execute_user = serializers.SlugRelatedField(slug_field='name', queryset=models.ExecuteUser.objects.all())

    class Meta:
        model = models.TestInfo
        # 所有字段
        fields = "__all__"
        # depth = 1 # 显示外键关联层

    def create(self, validated_data):
        # 指定 SlugRelatedField 后必须重写 create
        test_info = models.TestInfo.objects.create(**validated_data)
        return test_info


class ExecuteUserSerializers(serializers.ModelSerializer):
    """
    执行用户表序列化组件
    """
    class Meta:
        model = models.ExecuteUser
        fields = "__all__"

 

 

四 生成hypermedialink(极少数)

class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"
    # 生成连接,直接查看出版社详情
    publish = serializers.HyperlinkedIdentityField(view_name='ttt', lookup_field='publish_id', lookup_url_kwarg='pkk')
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        ret=obj.authors.all()
        ss=AuthorSerializer(ret,many=True)
        return ss.data
#--------------

res=BookSerializers(ret,many=True,context={'request': request})
#--------------

class Publish(APIView):
    def get(self,request,pkk):
        print(pkk)
        return HttpResponse('ok')
#----路由---
url(r'^publish/(?P<pkk>\d+)$', views.Publish.as_view(),name='ttt'),

 

五 序列化组件之请求数据校验和保存功能

 

class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model=Book
        fields="__all__"

#————————
class BookView(APIView):

    def post(self, request):

        # 添加一条数据
        print(request.data)

        bs=BookSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成记录
            return Response(bs.data)
        else:

            return Response(bs.errors)

 

class BookSerializer1(serializers.Serializer):
    title=serializers.CharField(error_messages={'required': '标题不能为空'})

#这种方式要保存,必须重写create方法

 

通过源码查看留的校验字段的钩子函数:

#is_valid---->self.run_validation-(执行Serializer的run_validation)-->self.to_internal_value(data)---(执行Serializer的run_validation:485行)
def validate_title(self, value):
        from rest_framework import exceptions
        raise exceptions.ValidationError('心情不好')
        return value

#全局
def validate(self, attrs):
    from rest_framework import exceptions
    if attrs.get('title')== attrs.get('title2'):
        return attrs
    else:
        raise exceptions.ValidationError('心急啊')

 

序列化组件源码分析

序列化组件,先调用__new__方法,如果many=True,生成ListSerializer对象,如果为False,生成Serializer对象 序列化对象.data方法--调用父类data方法---调用对象自己的to_representation(自定义的序列化类无此方法,去父类找) Aerializer类里有to_representation方法,for循环执行attribute = field.get_attribute(instance) 再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source,然后执行get_attribute方法,source_attrs 当参数传过去,判断是方法就加括号执行,是属性就把值取出来

图书的增删查改resful接口:

视图层:

from app01.My_Serialize import My_ser
from app01 import models
from rest_framework.response import Response
from rest_framework.views import APIView

class Book(APIView):

    def get(self,request):
        response = {"status":"100","msg":"成功"}
        book_list = models.Book.objects.all()

        book_ser = My_ser(book_list,many=True)
        response["book_list"] = book_ser.data
        return Response(response)

    def post(self,request):
        response = {"status":"100","msg":"成功"}
        # print(request.data)
        book_ser = My_ser(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            response['book'] = book_ser.data
        else:
            response['msg'] = book_ser.errors
        return Response(response)

class Books(APIView):

    def get(self,request,id):
        # response = {"status":"100","msg":"成功"}
        book_list = models.Book.objects.filter(pk=id).first()
        book_ser = My_ser(book_list,many=False)
        # response["book"] = book_ser.data
        return Response(book_ser.data)

    def put(self,request,id):
        book = models.Book.objects.filter(pk=id).first()
        obj = My_ser(data=request.data,instance=book)
        if obj.is_valid():
            obj.save()
            return Response(obj.data)
        else:
            return Response(obj.errors)

    def delete(self,request,id):
        models.Book.objects.filter(pk=id).delete()
        return Response("删除成功")
View Code

url:

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^book/', views.Book.as_view()),
    url(r'^books/(?P<id>\d+)', views.Books.as_view()),
]

 

posted @ 2019-02-27 11:27  萤huo虫  阅读(166)  评论(0编辑  收藏  举报