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

基本使用

-序列化
	-对象,转成json格式
用drf的序列化组件
  -定义一个类继承class BookSerializer(serializers.Serializer):
  -写字段,如果不指定source,字段名必须跟数据库字段名对应(source指定的值跟字段名不能重复)
  -source还可以指定方法
  -publish=serializers.SerializerMethodField()
	def get_publish(self,obj):
		obj.publish
		#obj.authors.all()

-Serializer
-ModelSerializer
	class Meta:
		# 指定表模型
		model = models.Book
		# 序列化所有字段
		fields = ‘__all__‘
		# 只想序列化title和id这俩字段
		# fields = [‘title‘, ‘id‘]
		# exclude 和fields 不要连用
		# exclude = [‘title‘]
		depth=1
         
          -反序列化:
            -保存
              ser=BookSer(data=传过来的字典)
              if ser.is_valid()
                ser.save()
            -取校验通过的数据:
              ser.data
            -修改
              ser=BookSer(data=传过来的字典,instance=要修改的对象)
              if ser.is_valid()
                ser.save()
              else:
                errors=ser.errors

          # 如果想让publish字段显示出版社的名字
            # publish = serializers.CharField(source=‘publish.name‘)
            # authors = serializers.SerializerMethodField()
            # def get_authors(self, obj):
            #     author_list = obj.authors.all()
            #     author_ser = AuthorSer(instance=author_list, many=True)
            #     return author_ser.data

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

view部分

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
<...   这一块代码最好新建一个 .py文件放在里面,这样的话看起来就不是那么乱了
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))

注意:

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‘)

小结

# 1 变量名和source指定的值不能一样
# 2 source=‘publish.name‘还支持继续 .
# 3 source 还支持方法(没用)
# 4 支持写方法,如下
	#方法一定传一个参数,是当前book对象
	publish_dic=serializers.SerializerMethodField()
	def get_publish_dic(self,obj):
	# 猜,这个obj应该是谁,当前book对象
	  return {‘id‘:obj.publish.pk,‘name‘:obj.publish.name}

在线格式化json
-https://www.json.cn/

rest-framework序列化之ModelSerializer

class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        # fields = "__all__"
        fields=[‘nid‘,‘title‘,‘authors‘,‘publish‘]
        # exclude=(‘nid‘,)   #不能跟fields同时用
        # depth = 1    #深度控制,写 几 往里拿几层,层数越多,响应越慢,官方建议0--10之间,个人建议最多3层
    publish=serializers.SerializerMethodField()
    def get_publish(self,obj):
        return obj.publish.name
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        ret=obj.authors.all()
        ss=AuthorSerializer(ret,many=True)
        return ss.data

生成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 django.shortcuts import render, HttpResponse
from django.http import JsonResponse
# Create your views here.
from django.views import View

class Test(View):
    def dispatch(self, request, *args, **kwargs):
        # 写代码
        obj = super().dispatch(request, *args, **kwargs)
        # 写代码
        return obj

    def get(self, request, *args, **kwargs):
        return HttpResponse(‘cbv_get‘)

    def post(self, request, *args, **kwargs):
        return HttpResponse(‘cbv_post‘)

user_list = [{‘id‘: 1, ‘name‘: ‘lqz‘, ‘age‘: 18}, {‘id‘: 2, ‘name‘: ‘egon‘, ‘age‘: 17},
             {‘id‘: 3, ‘name‘: ‘xiaohou‘, ‘age‘: 16}]

def users(request):
    response = {‘status‘: 100, ‘errors‘: None}
    if request.method == ‘GET‘:
        response[‘users‘] = user_list
        return JsonResponse(response, safe=False)
    if request.method == ‘POST‘:
        name = request.POST.get(‘name‘)
        age = request.POST.get(‘age‘)
        user_list.append({‘id‘: len(user_list) + 1, ‘name‘: name, ‘age‘: age})
        # response[‘user‘] = {‘id‘:len(user_list),‘name‘: name, ‘age‘: age}
        response[‘msg‘] = ‘新增成功‘
        return JsonResponse(response)

def user(request, id):
    response = {‘status‘: 100, ‘errors‘: None}
    if request.method == ‘GET‘:
        id = int(id)
        response[‘user‘] = user_list[id]
        return JsonResponse(response)

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request

# 基于drf写接口,写cbv
class DrfTest(APIView):

    def get(self, request, *args, **kwargs):
        # request是封装之后的request了,原来的request是request._request
        print(type(request._request))
        print(type(request))
        # 问:当前request对象并没有这些属性,但是能打印出来,为什么?
        # 修改了getattr
        print(request.method)
        print(request.POST)
        print(request.GET)
        # 就相当于:
        print(request.query_params)
        print(request._request.GET)
        response = {‘status‘: 100, ‘errors‘: None}
        response[‘users‘] = user_list
        # 用drf的Response,可以通过请求客户端来判断返回数据格式是什么样的
        return Response(response)
        # return JsonResponse(response)

    def post(self, request, *args, **kwargs):
        # post 提交的数据,urlencode,formdate,json格式,都能从data中取出来
        name = request.data.get(‘name‘)
        # request.FILES
        print(name)
        return HttpResponse(‘ok‘)

from app01 import models
from app01.MySer import BookSerializer

class Auth():
    def authenticate(self,request):
        pass

# 写一个获取所有图书的接口
class Books(APIView):
    authentication_classes=[Auth,]
    def get(self, request, *args, **kwargs):

        response = {‘status‘: 100, ‘msg‘: ‘成功‘}
        book_list = models.Book.objects.all()
        # 第一个参数是要序列化的queryset对象,如果序列化多条,必须指定many=True
        # 问?什么情况下many=False,instance=单个对象的时候
        book_ser = BookSerializer(book_list, many=True)
        print(book_ser.data)
        response[‘books‘] = book_ser.data
        return Response(response)

    def post(self, request):
        response = {‘status‘: 100, ‘msg‘: ‘成功‘}
        # 提交的字典
        # book = request.data
        # 传统方法,创建对象保存
        # 新方法,通过序列化组件保存,必须用继承自ModelSerializer
        # data注意是data
        book_ser = BookSerializer(data=request.data)
        # is_valid提交的字段校验通过
        if book_ser.is_valid():
            book_ser.save()
            response[‘book‘] = book_ser.data
        else:
            response[‘msg‘] = book_ser.errors
        # return Response(book_ser.data)
        return Response(response)

class Book(APIView):

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

    def put(self, request, id):
        response = {‘status‘: 100, ‘msg‘: ‘成功‘}
        book = models.Book.objects.filter(pk=id).first()
        # 修改的话,要把book对象传过来
        book_ser = BookSerializer(data=request.data, instance=book)
        # is_valid提交的字段校验通过
        if book_ser.is_valid():
            # save既可以修改,又可以更新
            book_ser.save()
            response[‘book‘] = book_ser.data
        else:
            response[‘msg‘] = book_ser.errors
        # return Response(book_ser.data)
        return Response(response)

    def delete(self,request,id):
        response = {‘status‘: 100, ‘msg‘: ‘删除成功‘}
        book = models.Book.objects.filter(pk=id).delete()
        return Response(response)

模板层

from django.db import models

# Create your models here.
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 test(self):
        return self.title + str(self.price)

    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
    # return str(self.pk)

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

自己手动创建的序列化组件层

from rest_framework import serializers

# from rest_framework.request import Request

class AuthorSer(serializers.Serializer):
    id = serializers.CharField()
    name = serializers.CharField()
    age = serializers.CharField()

# class BookSerializer(serializers.Serializer):
#     id = serializers.CharField()
#     # 通过source可以改名
#     name = serializers.CharField(source=‘title‘)
#     price = serializers.CharField()
#
#     xxx = serializers.CharField(source=‘test‘)
#     # 1 变量名和source指定的值不能一样
#     # 2 source=‘publish.name‘还支持继续 .
#     # 3 source 还支持方法(没用)
#     # publish_name = serializers.CharField(source=‘publish.name‘)
#     # publish_id = serializers.CharField(source=‘publish.pk‘)
#     # 4 支持写方法,如下
#         #方法一定传一个参数,是当前book对象
#     publish_dic=serializers.SerializerMethodField()
#     def get_publish_dic(self,obj):
#         # 猜,这个obj应该是谁,当前book对象
#         return {‘id‘:obj.publish.pk,‘name‘:obj.publish.name}
#     authors=serializers.SerializerMethodField()
#     # def get_authors(self,obj):
#     #     # 所有作者queryset对象
#     #     author_list=obj.authors.all()
#     #     ll=[ {‘name‘:author.name,‘id‘:author.pk} for author in author_list]
#     #     return ll
#     def get_authors(self,obj):
#         # 所有作者queryset对象
#         author_list=obj.authors.all()
#         author_ser=AuthorSer(instance=author_list,many=True)
#         return author_ser.data
# ModelSerializer跟表模型绑定的序列化
from app01 import models

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        # 指定表模型
        model = models.Book
        # 序列化所有字段
        fields = ‘__all__‘
        # 只想序列化title和id这俩字段
        # fields = [‘title‘, ‘id‘]
        # exclude 和fields 不要连用
        # exclude = [‘title‘]
        # 深度,表示连表的深度
        # 不建议使用:下几层要取得参数不能控制,官方建议不要超过10,我给你的建议不要超过3
        # depth=1
        # 全取出来之后,可以在后面覆盖之前的值
        # 如果想让publish字段显示出版社的名字
        # publish = serializers.CharField(source=‘publish.name‘)
        # authors = serializers.SerializerMethodField()
        # def get_authors(self, obj):
        #     author_list = obj.authors.all()
        #     author_ser = AuthorSer(instance=author_list, many=True)
        #     return author_ser.data

    title = serializers.CharField(max_length=6, min_length=3, error_messages={‘max_length‘: ‘太长了‘})

    # 也有局部钩子和全局钩子
    def validate_title(self, value):
        from rest_framework import exceptions
        print(value)
        if value.startswith(‘sb‘):
            raise exceptions.ValidationError(‘不能以sb开头‘)
        return value
    # def validate_title(self, value):
    #     from rest_framework import exceptions
    #     raise exceptions.ValidationError(‘看你不顺眼‘)
    #     return value

路由

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r‘^admin/‘, admin.site.urls),
    url(r‘^users/‘, views.DrfTest.as_view()),
    # 在这写的实际上就是as_view()内view的内存地址
    url(r‘^books/‘, views.Books.as_view()),
    url(r‘^book/(?P<id>\d+)‘, views.Book.as_view()),
]

  

原文地址:https://www.cnblogs.com/596014054-yangdongsheng/p/10228812.html

时间: 2024-10-25 08:20:33

Restful framework【第三篇】序列化组件的相关文章

Entity Framework 第三篇 实体特性声明

Entity Framework中对实体的特性声明有着严格的要求 1.实体必须要有主键特性,但是如果实体没有主键特性那怎么办? public int ExecuteSqlCommand(string sql, params SqlParameter[] paras) { if (this.IsTransaction) { if (dbContext.Database.CurrentTransaction == null) { dbContext.Database.BeginTransaction

Restful framework【第九篇】分页器

基本使用 分页 -简单分页 page_size = api_settings.PAGE_SIZE :每页显示条数 page_query_param = 'page' :查询的页码数 page_size_query_param = None :每页最大显示条数 -如果我要的数据是第一页显示10条:http://127.0.0.1:8000/books/?ccc=10&page=1 -如果我要的是第二页显示5条:http://127.0.0.1:8000/books/?ccc=5&page=2

Restful framework【第二篇】APIView

安装djangorestframework 方式一:pip3 install djangorestframework 方式二:pycharm图形化界面安装 方式三:pycharm命令行下安装(装在当前工程所用的解释器下) djangorestframework的APIView分析 as_view方法 @classmethod def as_view(cls, **initkwargs): """ Store the original class on the view fun

Restful framework【第一篇】RESTful 规范

什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态 REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” 所有的数据,

Django Restful Framework【第四篇】版本、解析器、序列化和请求数据验证

一.版本 程序也来越大时,可能通过版本不同做不同的处理 没用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':'版本一的内容'

RESTful【第三章】:序列化组件的使用及接口设计

序列化组件的使用及接口设计 一.Django原生的serializer(序列化) 使用步骤: 1.导入模块 from django.core.serializers import serialize 2.获取queryset 3.对queryset进行序列化 4.将序列化后的数据,响应给客户端 实例: #1.导入Django自带的原生的序列化模块 from django.core.serializers import serialize class CourseView(APIView): de

Django Rest Framework --- 序列化组件

一.序列化组件的作用 在前后端分离开发时,前端与后端用来交互的数据的格式是一致的(数据格式为字符串的json数据),于是后端程序员在传递数据时,便要将数据封装成符合格式的数据,如果不借助方法,手动进行数据封装,会非常的浪费时间,在Django rest framework中的序列化组件帮我们解决了这个问题. 二.Django自带的序列化组件 from django.core import serializers def test(request): book_list = Book.object

第三章 restframework——序列化组件

第三章 restframework--序列化组件 一.django自带的序列化组件serializers 二.restframework的序列化组件Serializer 三.restframework的序列化组件ModelSerializer 四.restframework的序列化组件请求数据校验和保存功能(钩子) 五.restframework的序列化组件源码分析 一.django自带的序列化组件serializers from django.core import serializers d

django rest framework 序列化组件总结

序列化组件总结 一. 序列化组件本质上为了实现前后端分离,而进行json序列化的一个组件形式,极大方便了解析数据的作用 二. 所有序列化是基于APIView 解析器实现的,通过内部的多继承关系方便实现进行数据序列化的实现 三 使用方式 1.基于APIView 引入  from rest_framework.views import APIView 2.返回的请求用 Response  from rest_framework.response import Response 3.开始进行创建序列化