现在对应的模块APP创建serializers.py文件:选择一种来使用,推荐用ModelSerializer
和Serializer的不同点,通常用于需要与Django模型定义紧密映射的序列化程序类:
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)
基础类,下文基本使用这个类来进行。
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)
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
用的是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
序列化可以理解为:把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)
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
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
# 这个是接收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
(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: 瓜子>
>>>
当我们打开一个之前设定好的网页时,请求方式只有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请求方式:
这里要启动前端服务器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>