DRF框架的使用入门(二)Serializer序列化器/串行器

DRF框架的使用入门(二)序列化器/串行器

  • 先创建serializers.py定义序列化器
    • 用ModelSerializer创建序列化器
    • 用基础类Serializer创建序列化器:
  • 在views.py写入内容
  • urls.py写路由逻辑
  • 用shell来写调试数据库数据序列化查询
  • 序列化与反序列化
  • 保存实例
    • 如果我们希望能够基于已验证的数据返回完整的对象实例,则需要实现一个或两个.create()和.update()方法
    • 如果对象实例与Django模型相对应,则还需要确保这些方法将对象保存到数据库中。例如,如果Comment是Django模型,方法可能如下所示:
  • 验证
    • 字段级验证(现场级)
    • 对象验证
    • create和update方法,对象实例为django模型时:
    • 用shell来调试验证过程
  • 为网页添加PUT请求方式
    • 1.postman方式发送PUT请求:
    • 2.前端ajax发送PUT请求:

前文:推荐看官网
环境:版本(django1.11, python3.5),适用于前后端分离项目

先创建serializers.py定义序列化器

现在对应的模块APP创建serializers.py文件:选择一种来使用,推荐用ModelSerializer

用ModelSerializer创建序列化器

和Serializer的不同点,通常用于需要与Django模型定义紧密映射的序列化程序类:

  • 它将根据模型自动为您生成一组字段。
  • 它将自动为序列化程序生成验证器,例如UNIQUE_CONITY验证器。
  • 它会做这两个方法的简单默认实现。.create()和.update().
from rest_framework import serializers
from goods.models import GoodsInfo
# 定义一些序列号程序


class GoodsInfoSerializer(serializers.ModelSerializer):
    # 创建序列化器
    class Meta:
        # 定义元类
        # model指明了当前的序列化器和哪个模型产生联系
        model = GoodsInfo
        fields = '__all__'   # 意思是所有的字段都要
        # 这样写是自己选择需要的字段
        # fields = ('url', 'username', 'email', 'groups')

用shell查看自动生成的内容:

>>> from goods.serializers import *
>>> ser = GoodsInfoSerializer()
>>> ser
GoodsInfoSerializer():
    id = IntegerField(label='ID', read_only=True)
    name = CharField(max_length=50)
    pub_date = DateField(allow_null=True, label='商品发布时间', required=False)
    is_delete = BooleanField(label='逻辑删除', required=False)
    readcount = IntegerField(label='流量', max_value=2147483647, min_value=-2147483648, required=False)
    price = CharField(max_length=10)

用基础类Serializer创建序列化器:

基础类,下文基本使用这个类来进行。

class GoodsInfoNewSerializer(serializers.Serializer):
    # 基础序列化器需要填id,可以设置备注和只读属性
    id = serializers.IntegerField(label='主键', read_only=True)
    name = serializers.CharField(max_length=50)
    price = serializers.CharField(max_length=11)

    # readonly和required只能设置一种
    # 设置外键,required表示在反序列化中必须传递的值
    # addkey = serializers.StringRelatedField(label='外键地址id', required=True)

    # 这个是接收post请求
    def create(self, validated_data):
        return GoodsInfo.objects.create(**validated_data)

在views.py写入内容

from django.shortcuts import render
from django.http import HttpResponse
from rest_framework.viewsets import ModelViewSet
from goods.models import GoodsInfo
from goods.serializers import GoodsInfoSerializer


# Create your views here.

class GoodsInfoView(ModelViewSet):
    # 先导包ModelViewSet和数据库Model和serializers下的类
    # queryset是一个查询集,存储所有的数据库查询之后的数据,是一个属性不能修改名字
    queryset = GoodsInfo.objects.all()
    '''serializer_class用来指定再当前的视图立面进行序列化和反序列化时
    使用的序列化器(也叫串行器)
    '''
    serializer_class = GoodsInfoSerializer
	# 根据需要选择Serializer
   	# serializer_class = GoodsInfoNewSerializer

urls.py写路由逻辑

用的是rest_framework的方法:

from django.conf.urls import url
from goods.views import *
from rest_framework.routers import DefaultRouter


# 定义视图处理的路由器
router = DefaultRouter()
# 在路由器中注册视图集
router.register('goods', GoodsInfoView, base_name='')

urlpatterns = [
    # 要用RSF的定义路由方法
]
urlpatterns += router.urls

用shell来写调试数据库数据序列化查询

DRF框架的使用入门(二)Serializer序列化器/串行器_第1张图片

序列化与反序列化

序列化可以理解为:把python的对象编码转换为json格式的字符串,
反序列化可以理解为:把json格式字符串解码为python数据对象

用的官方文档的实例:

from datetime import datetime
# 创建一个简单的对象
class Comment(object):
    def __init__(self, email, content, created=None):
       self.email = email
       self.content = content
       self.created = created or datetime.now()

comment = Comment(email='[email protected]', content='foo bar')

from rest_framework import serializers
# 我们将声明一个序列化程序,用于序列化和反序列化对应于Comment物品。
class CommentSerializer(serializers.Serializer):
	email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()
# 我们现在可以用CommentSerializer若要序列化注释或注释列表,请执行以下操作。再次使用Serializer类看起来很像使用Form班级,等级。
serializer = CommentSerializer(comment)
print(serializer.data)
# {'created': '2019-06-05T09:11:34.510864+08:00', 'content': 'foo bar', 'email': '[email protected]'}
from rest_framework.renderers import JSONRenderer
# 至此,我们已经将模型实例转换为Python本机数据类型。为了完成序列化过程,我们将数据呈现到json
json = JSONRenderer().render(serializer.data)
print(json)
# b'{"email":"[email protected]","content":"foo bar","created":"2019-06-05T09:11:34.510864+08:00"}'
import io
from rest_framework.parsers import JSONParser
# 获取到的为字节流数据
# 开始反序列化,首先,我们将流解析为Python本地数据类型.。
stream = io.BytesIO(json)
data = JSONParser().parse(stream)
print(data)
# {'created': '2019-06-05T09:11:34.510864+08:00', 'content': 'foo bar', 'email': '[email protected]'}
# 然后,我们将这些本机数据类型还原到已验证数据的字典中。
serializer = CommentSerializer(data=data)
# 判断是否验证成功
print(serializer.is_valid())
# True
# 打印验证好的数据
print(serializer.validated_data)

保存实例

如果我们希望能够基于已验证的数据返回完整的对象实例,则需要实现一个或两个.create()和.update()方法


class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

    def create(self, validated_data):
    	# 通过验证过的数据返回完整的对象实例
        return Comment(**validated_data)

    def update(self, instance, validated_data):
    	# 更新
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        return instance

如果对象实例与Django模型相对应,则还需要确保这些方法将对象保存到数据库中。例如,如果Comment是Django模型,方法可能如下所示:

    def create(self, validated_data):
        return Comment.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        instance.save()
        return instance

验证

有时候我们希望有自己的验证内容,因此需要重写父类方法来进行验证

字段级验证(现场级)

def validate_name(self, value):
        # 单个字段的校验
        if len(value) < 0:
            # 设置为0是注释掉的意思
            raise serializers.ValidationError('商品名字必须大于5位')
        return value

对象验证

def validate(self, attrs):
        # is_valid()会自动调用这个方法
        # 重写这个方法可以自己对整个对象进行自定义验证方式
        # 这个attrs就是要验证的数据
        print(attrs.get('name'))
        if len(attrs['name']) < 0:
            raise serializers.ValidationError('这是商品名验证')
        return attrs

create和update方法,对象实例为django模型时:

# 这个是接收post请求
    def create(self, validated_data):
        print('###############################')
        print(validated_data)
        return GoodsInfo.objects.create(**validated_data)

    def update(self, instance, validated_data):
        # 处理PUT请求
        instance.id = validated_data.get('id', instance.id)
        instance.name = validated_data.get('name', instance.name)
        instance.price = validated_data.get('price', instance.price)
        instance.save()
        return instance

用shell来调试验证过程

  • ser.is_valid(raise_exception=True) 设置为True时会抛出异常信息
  • ser.errors也可以抛出异常信息
  • 下文ser1做了一个错误的示范,ser2的内容是符合数据库设定时必填的内容
  • is_valid会调用上文的validata()方法,validated_data会调用create()方法
(django_py3) python@ubuntu:~/Desktop/testproject_t$ python manage.py shell
Python 3.5.2 (default, Jul  5 2016, 12:43:10) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from goods.serializers import *

>>> data = {'pub_date':1}
>>> ser1 = GoodsInfoNewSerializer(data)
>>> ser1.errors
{'name': [ErrorDetail(string='该字段是必填项。', code='required')], 'price': [ErrorDetail(string='该字段是必填项。', code='required')]}
>>> ser1.is_valid(raise_exception=True)
Traceback (most recent call last):
  File "", line 1, in <module>
  File "/home/python/.virtualenvs/django_py3/lib/python3.5/site-packages/rest_framework/serializers.py", line 244, in is_valid
    raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'name': [ErrorDetail(string='该字段是必填项。', code='required')], 'price': [ErrorDetail(string='该字段是必填项。', code='required')]}


>>> data={'name':'瓜子', 'price':'10'}
>>> ser2 = GoodsInfoNewSerializer(data=data)
>>> ser2.is_valid()
瓜子
True
>>> ser2.validated_data
OrderedDict([('name', '瓜子'), ('price', '10')])
>>> ser2.save()
###############################
{'name': '瓜子', 'price': '10'}
<GoodsInfo: 瓜子>
>>> 

为网页添加PUT请求方式

当我们打开一个之前设定好的网页时,请求方式只有GET,POST,HEAD,OPTIONS,要使用序列化器中已经的update方法得使用PUT请求才能修改数据(而且此时我修改了models.py内容,修改完记得数据库迁移)。
此时models.py内容为:

class GoodsInfo(models.Model):
    # db_column数据库字段名 verbosename是备注
    # null=True可以为空
    name = models.CharField(db_column='goodsname', max_length=50)
    pub_date = models.DateField(verbose_name='商品发布时间', null=True)
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    readcount = models.IntegerField(default=0, verbose_name='流量')
    price = models.CharField(max_length=10)

    class Meta:
        # 元类
        db_table = 'goodsinfo'
        verbose_name_plural = '产品信息'

    def __str__(self):
        return self.name

修改views.py内容,添加PUT请求方式:

class GoodsInfoView(ModelViewSet):
    # 先导包ModelViewSet和数据库Model和serializers下的类
    # queryset是一个查询集,存储所有的数据库查询之后的数据,是一个属性不能修改名字
    queryset = GoodsInfo.objects.all()
    '''serializer_class用来指定再当前的视图立面进行序列化和反序列化时
    使用的序列化器(也叫串行器)'''
    serializer_class = GoodsInfoNewSerializer

	# 添加PUT请求方式
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

在urls.py配置跳转逻辑,因为django rest framework必须要有pk参数,因此传入一个pk参数,pk参数数值等于id值:

from django.conf.urls import url
from goods.views import *
from rest_framework.routers import DefaultRouter
# from rest_framework.authtoken.views import obtain_auth_token


# 定义视图处理的路由器
router = DefaultRouter()
# 在路由器中注册视图集
router.register('showgoods', GoodsInfoView, base_name='hello')
# base_name一样时在drf管理界面会显示路径一样,最好备注下
router.register('newgoods', GoodsInfoView, base_name='newgoods')
# 下面是两种配置路由的方式
urlpatterns = [
    # ?P<>这个里面是传参值,对应方法需要写传参,\d+是传给他的值
    url(r'^(?P\d+)+(/showgoods/)$', GoodsInfoView.as_view({'get':'retrieve', 'delete': 'destroy','post':'create','put':'update'}))
]

# 要用RSF的定义路由方法
urlpatterns += router.urls

此时已经配置好,可以用两种方法来调试PUT请求方式:

1.postman方式发送PUT请求:

DRF框架的使用入门(二)Serializer序列化器/串行器_第2张图片

2.前端ajax发送PUT请求:

这里要启动前端服务器live-server,没有配置的可以看:https://blog.csdn.net/paul0926/article/details/90750408
然后打开网页,点击按钮即可


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="jquery-1.12.4.min.js">script>
    <script type="text/javascript">
        $(function () {

            $('#btn').click(function () {
                var post_data = {
                    'name': '海鲜面',
                    'price': '21'
                };
                /* post_data = JSON.stringify(post_data); */

                $.ajax({
                	/*这是对应网址*/
                    url:'http://127.0.0.1:8000/goods/12/showgoods/',
                    type: 'PUT',
                    data: post_data,

                    success: function (data) {
                        alert('提交成功');
                        console.log(typeof data);
                    }
                })
            })
        })

    script>
head>
<body>
<button id="btn">提交数据button>
body>
html>

你可能感兴趣的:(Django)