首页 > 其他分享 >django views 序列化

django views 序列化

时间:2023-06-12 10:14:18浏览次数:55  
标签:serializers 验证 views django content 序列化 data class

   REST framework中的序列化类与Django的FormModelForm类非常相似。我们提供了一个Serializer类,它提供了一种强大的通用方法来控制响应的输出,以及一个ModelSerializer类,它为创建处理模型实例和查询集的序列化提供了有效的快捷方式。

Serializers 

  序列化器允许把像查询集和模型实例这样的复杂数据转换为可以轻松渲染成JSONXML或其他内容类型的原生Python类型。序列化器还提供反序列化,在验证传入的数据之后允许解析数据转换回复杂类型。不仅仅有序列化功能,更提供了数据验证的功能(与django中的form类似)

 

牛刀小试:

    让我们从创建一个简单的对象开始,我们可以使用下面的例子:

复制代码
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')
复制代码

    然后声明一个序列化器,我们可以使用它来序列化和反序列化与Comment对象相应的数据。

声明一个序列化器看起来非常像声明一个form:

复制代码
from rest_framework import serializers

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

复制代码

1、序列化与反序列化

复制代码
# 序列化(Python原生的数据类型dict)
serializer = CommentSerializer(comment)
serializer.data   # {'email': '[email protected]', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}

#转化为json类型 from rest_framework.renderers import JSONRenderer json = JSONRenderer().render(serializer.data) json # b'{"email":"[email protected]","content":"foo bar","created":"2016-01-27T15:17:10.375877"}'


# 反序列化 from django.utils.six import BytesIO from rest_framework.parsers import JSONParser stream = BytesIO(json) data = JSONParser().parse(stream)
复制代码

2、保存实例

如果我们希望能够返回基于验证数据的完整对象实例,我们需要实现其中一个或全部实现.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)
        # return Comment.objects.create(**validated_data) # model对象

    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() model对象
        return instance
复制代码

ps:.create().update()方法都是可选的。你可以根据你序列化器类的用例不实现、实现它们之一或都实现。

现在当我们反序列化数据的时候,基于验证过的数据我们可以调用.save()方法返回一个对象实例。

comment = serializer.save()

调用.save()方法将创建新实例或者更新现有实例,具体取决于实例化序列化器类的时候是否传递了现有实例:

# .save() will create a new instance.
serializer = CommentSerializer(data=data)

# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)

默认情况下,序列化程序必须为所有必填字段传递值,否则会引发验证错误。你可以使用partial参数以允许部分更新

# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data,partial=True)

 3、验证

    反序列化数据的时候,你始终需要先调用is_valid()方法,然后再尝试去访问经过验证的数据或保存对象实例。如果发生任何验证错误,.errors属性将包含表示生成的错误消息的字典。例如:

serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors   # {'email': [u'Enter a valid e-mail address.'], 'created': [u'This field is required.']}

字典里的每一个键都是字段名称,值是与该字段对应的任何错误消息的字符串列表。non_field_errors键可能存在,它将列出任何一般验证错误信息。non_field_errors的名称可以通过REST framework设置中的NON_FIELD_ERRORS_KEY来自定义。 当对对象列表进行序列化时,返回的错误是每个反序列化项的字典列表。

抛出无效数据的异常

.is_valid()方法使用可选的raise_exception标志,如果存在验证错误将会抛出一个serializers.ValidationError异常。

这些异常由REST framework提供的默认异常处理程序自动处理,默认情况下将返回HTTP 400 Bad Request响应。

# 如果数据无效就返回400响应
serializer.is_valid(raise_exception=True)

字段级别的验证

    你可以通过向你的Serializer子类中添加.validate_<field_name>方法来指定自定义字段级别的验证。这些类似于Django表单中的.clean_<field_name>方法。

    这些方法采用单个参数,即需要验证的字段值。

    你的validate_<field_name>方法应该返回一个验证过的数据或者抛出一个serializers.ValidationError异常。例如:

复制代码
from rest_framework import serializers

class BlogPostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    content = serializers.CharField()

    def validate_title(self, value):
        """
        Check that the blog post is about Django.
        """
        if 'django' not in value.lower():
            raise serializers.ValidationError("Blog post is not about Django")
        return value
复制代码

注意: 如果你在序列化器中声明<field_name>的时候带有required=False参数,字段不被包含的时候这个验证步骤就不会执行。

对象级别的验证

    要执行需要访问多个字段的任何其他验证,请添加一个.validate()方法到你的Serializer子类中。这个方法采用字段值字典的单个参数,如果需要应该抛出一个 ValidationError异常,或者知识返回经过验证的值。例如:

复制代码
from rest_framework import serializers

class EventSerializer(serializers.Serializer):
    description = serializers.CharField(max_length=100)
    start = serializers.DateTimeField()
    finish = serializers.DateTimeField()

    def validate(self, data):
        """
        Check that the start is before the stop.
        """
        if data['start'] > data['finish']:
            raise serializers.ValidationError("finish must occur after start")
        return data
复制代码

验证器

序列化器上的各个字段都可以包含验证器,通过在字段实例上声明,例如:

复制代码
def multiple_of_ten(value):
    if value % 10 != 0:
        raise serializers.ValidationError('Not a multiple of ten')

class GameRecord(serializers.Serializer):
    score = IntegerField(validators=[multiple_of_ten])
复制代码

序列化器类还可以包括应用于一组字段数据的可重用的验证器。validators给我们提供了很多很好的功能:UniqueValidator,UniqueTogetherValidator等。

这些验证器要在内部的Meta类中声明,如下所示:

UniqueTogetherValidator:(表示联合唯一)

复制代码
class EventSerializer(serializers.Serializer):
    name = serializers.CharField()
    room_number = serializers.IntegerField(choices=[101, 102, 103, 201])
    date = serializers.DateField()

    class Meta:
        # 每间屋子每天只能有1个活动。
        validators = UniqueTogetherValidator(
            queryset=Event.objects.all(),
            fields=['room_number', 'date']
        )
复制代码

UniqueValidator:

username = serializers.CharField(
        max_length=11, 
        min_length=11,
        validators=[UniqueValidator(queryset=UserProfile.objects.all())
    )

更多信息请参阅 validators文档

 

ModelSerializer

    它为创建用于处理模型实例和查询集的序列化程序提供了有用的快捷实现方式。自动创建一个Serializer类,字段与model的字段一一对应。

ModelSerializer类与常规Serializer类相同,不同之处在于:

  • 它会根据模型自动生成一组字段。
  • 它会自动为序列化类生成验证器,例如unique_together验证器。
  • 它包含.create()和.update()的简单默认实现。它能够满足将post或patch上来的数据进行进行直接地创建与更新,除非有额外需求,那么就可以重载create与update方法。

声明ModelSerializer如下,在Meta中设置fields字段,系统会自动进行映射成序列化字段,省去每个字段再写一个field。

1、序列化

复制代码
class CourseSerializer(serializers.ModelSerializer):
    """
    课程序列化
    """class Meta:
        model = models.Course
        # 字段显示
        fields = ['id','title','level'] # 
        # fields = '__all__':  表示所有字段 
        # exclude = ('add_time',): 除去指定的某些字段
        # 只读字段  ---多个字段只读,我们可以这样设置,不用每个字段都设置read_only=True
        read_only_fields=(“field_name”,) # editable=False、AutoField 默认只读,不用添加
复制代码

2、关于外键

任何关系(如模型上的外键)都将映射到PrimaryKeyRelatedField(但获得外键类别的id)。除非在序列化关系文档中指定,否则默认不包括反向关系。

复制代码
class CourseDetailSerializer(serializers.ModelSerializer):
    """
    课程详细序列化
    """
    # choice
    level = serializers.CharField(source='course.get_level_display')
    # one2one/fk
    # 外键方式一 需要单个信息
    title = serializers.ReadOnlyField(source='course.title')
    # 外键方式二 需要更多信息
    course=CourseSerializer(many=True)

    # m2m 方法一:使用SerializerMethodField(method_name=None)方法,but该方法为readonly字段。
    #---当不指定method_name ,默认为get_field_name,
    recommends = serializers.SerializerMethodField()
    chapter = serializers.SerializerMethodField()


    class Meta:
        model = models.CourseDetail
        fields = ['course','title','img','level','slogon','why','recommends','chapter']
        # 外键方式三 depth 表示应该遍历的关联深度
        # depth = 1  另外访问时显示外键字段的所有信息,但是只读的,不可编辑,即新建时不能传值
   def get_recommends(self,obj): 

       # 获取推荐的所有课程 
       queryset = obj.recommend_courses.all() 
       return [{'id':row.id,'title':row.title} for row in queryset] 

   def get_chapter(self,obj): 

      # 获取推荐的所有课程 
      queryset = obj.course.chapter_set.all() 
      return [{'id':row.id,'name':row.name} for row in queryset]
复制代码

ModelSerializer主要需要解决的2个问题:

 1,某个字段不属于指定model,它是write_only,需要用户传进来,但我们不能对它进行save( ),因为ModelSerializer是基于Model,这个字段在Model中没有对应,这个时候,我们需要重载validate!
  如在用户注册时,我们需要填写验证码,这个验证码只需要验证,不需要保存到用户这个Model中:
def validate(self, attrs):
        del attrs["code"]
        return attrs
2,某个字段不属于指定model,它是read_only,只需要将它序列化传递给用户,但是在这个model中,没有这个字段!我们需要用到SerializerMethodField。
  假设需要返回用户加入这个网站多久了,不可能维持这样加入的天数这样一个数据,一般会记录用户加入的时间点,然后当用户获取这个数据,我们再计算返回给它。 复制代码
class UserSerializer(serializers.ModelSerializer):    
    days_since_joined = serializers.SerializerMethodField()
        
    class Meta:
        model = User

    # 方法写法:get_ + 字段
    def get_days_since_joined(self, obj):
    # obj指这个model的对象
        return (now() - obj.date_joined).days

标签:serializers,验证,views,django,content,序列化,data,class
From: https://www.cnblogs.com/weifeng1463/p/17474177.html

相关文章

  • Django学习之路
    Django学习之路基于Jason的视频,收益匪浅.谢谢Jason的教诲.1、Django前戏2、Django基础3、Django路由层4、Django视图层......
  • Java反序列化之Commons-Collection篇04-CC4链
    <1>环境分析因为CommonsCollections4除4.0的其他版本去掉了InvokerTransformer不再继承Serializable,导致无法序列化。同时CommonsCollections4的版本TransformingComparator继承了Serializable接口,而CommonsCollections3里是没有的。这个就提供了一个攻击的路径jd......
  • Python Django Restful API simple JWT
    在这种情况下,您可以创建一个自定义权限类,并检查用户所属的任何组是否具有相应的权限。例如,您可以在Django后台为每个组定义一个具有读取权限(`view`权限)的权限对象。然后,在自定义权限类中检查用户组是否具有此权限。首先,在`models.py`文件中创建一个新的权限。例如,创建一个名......
  • 不停机条件下部署 Django 应用
    当我们上线新的服务应用时,经常不得不重启Web服务器以完成部署。但这会对用户造成一定影响,特别是服务器处于繁忙状态时,问题更严重。本文中,作者将针对这一问题,讲述其如何在不停机条件下部署Django应用。当我的网站healthchecks.io每秒接收的请求次数超过一次之后,我就非常清楚地认识......
  • Django站点静态文件缓存相关问题
    《高性能网站建设指南》中有一条建议,为网站的页面、文件“添加Expires头”。这么做的好处就不多说了,实现方式也比较简单,不过,真的实施这条建议时,还是有许多问题需要考虑。通常情况下,我们需要将图片、js、css等不会经常更新的文件缓存起来,一般来说,配置服务器,为它们设置一个较远的......
  • Django使用redis缓存服务器
        redis相信大家都很熟悉了,和memcached一样是一个高性能的key-value数据库,至于什么是缓存服务器,度娘都有很明白的介绍了,我在这里就不一一介绍了。那我们一般什么情况下才会使用缓存服务器呢?可不是什么情况都需要的哦,一般来说是在需要频繁对一个字段读取的时候才会需要将这......
  • Django的项目框架搭建
    1.1创建项目project,创建应用myapp#创建项目框架tpdemodjango-adminstartprojecttpdemocdproject#在项目中创建一个应用pythonmanage.pystartappmyapp#创建模板目录mkdirtemplatesmkdirtemplates/myapp如图所示1.2编辑tpdemo/tpdemo/sittings.py文件,配置......
  • Vue_Django 登录注册+图书管理系统
    Vue前端注册页面点击查看代码<template><divclass="register"><el-row:gutter="20"><el-col:span="12":offset="6"><divclass="grid-contentbg-purple">&......
  • Django3中分组查询的一个坑
    最近在学习django的分组查询,发现使用通常的values加annotate方法,获取不到我想要的结果,后来通过查询官方文档得到答案一、问题描述1.1模型fromdjango.dbimportmodels#Createyourmodelshere.classGoods(models.Model):g_name=models.CharField(max_length=......
  • Django的staticfiles库
    staticfiles库是Django提供的一个用于管理静态文件的库,它提供了一些工具和函数来帮助开发者在Django应用程序中管理和提供静态文件服务。在Django应用程序中,静态文件通常包括CSS样式文件、JavaScript脚本文件、图像文件以及其他一些资源文件。这些静态文件通常需要被服......