Django Rest Framework之序列化

本文详细介绍了Django Rest Framework(DRF)中的序列化,包括安装DRF,使用APIView,serializers.Serializer序列化数据模型,以及serializers.ModelSerializer序列化,深度探讨了序列化过程中的参数设置、数据校验、反序列化、增删改查操作等关键点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:安装DRF

pip install django==2.1.7
pip install djangorestframework

settings配置文件中注册rest_framework

INSTALLED_APPS = [
    ...............
    'rest_framework',
]

二:APIView

Django rest framework
APIView与View的区别:

  1. APIView继承了View
  2. APIView中重写了as_view()方法以及dispatch()方法
  3. 在dispatch()里重新封装了request对象,request = Request(),而旧的request对象变成了_request
  4. 获取get请求参数使用:request.query_params()
  5. 获取post请求参数使用:request.data()

不管是View还是APIView最开始调用的都是as_view()方法
APIView
APIView继承了View, 并且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证
那我们看看View中的as_view()方法做了什么~
APIView
在View中的as_view方法返回了view函数,而view函数执行了self.dispatch()方法,而这里的dispatch方法是APIView中的方法
APIView
我们去initialize_request中看下把什么赋值给了request,并且赋值给了self.request, 也就是我们在视图中用的request.xxx到底是什么
APIView
我们看到,这个方法返回的是Request这个类的实例对象~~我们注意我们看下这个Request类中的第一个参数request,这是django中旧的request
APIView
这个Request类把原来的request赋值给了self._request, 也就是说以后_request是我们老的request,新的request是我们这个Request类。那我们继承APIView之后请求来的数据都在哪呢
APIView
我们用了rest_framework框架以后,我们的request是重新封装的Request类,request.query_params 存放的是我们get请求的参数,request.data 存放的是我们所有的数据,包括post请求的以及put,patch请求,相比原来的django的request,我们现在的request更加精简,清晰了。

三:serializers.Serializer序列化

3.1 数据模型

from django.db import models
__all__ = ['Book', 'Publisher', 'Author']
class Book(models.Model):
    title = models.CharField(max_length=32)
    CHOICES = (
        (1, 'Python'),
        (2, 'Linux'),
        (3, 'Go')
    )
    category = models.IntegerField(choices=CHOICES)
    pub_time = models.DateField()
    publisher = models.ForeignKey(to = 'Publisher', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to = 'Author')
class Publisher(models.Model):
    title = models.CharField(max_length=32)
class Author(models.Model):
    name = models.CharField(max_length=32)

3.2 创建序列化器

在app目录下创建serializers.py文件

from rest_framework import serializers
from .models import Book

class PublisherSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField(max_length=32)

class AutherSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField(max_length=32)

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)  # required=False 指明反序时(前端提交数据过来)不做校验
    title = serializers.CharField(max_length=32)
    pub_time = serializers.DateField()
    category = serializers.CharField(source='get_category_display', read_only=True)
    # 外键关系的序列化是嵌套的序列化对象;内部通过外键关系的id找到publisher对象,再使用PublisherSerializer(publisher对象)
    publisher = PublisherSerializer(read_only=True)			# 嵌套序列化器
    authors = AutherSerializer(many=True, read_only=True)  # 多对多关系需要加上参数:many = True
    # read_only:指明该字段只做序列化,反序列化时不走该字段;那么反序列化时就必须重新指定字段名
    # write_only:指明该字段只做反序列化
    post_category = serializers.IntegerField(write_only=True)
    publisher_id = serializers.IntegerField(write_only=True)
    author_list = serializers.ListField(write_only=True)

    def create(self, validated_data):
        # validated_data 校验通过的数据
        # 通过ORM操作给Book表添加数据
        # print(validated_data)
        # {'title': 'Die Hard', 'pub_time': datetime.date(2020, 1, 12), 'post_category': 1, 'publisher_id': 1, 'author_list': [1, 2]}
        book_obj = Book.objects.create(
            title=validated_data['title'],
            pub_time=validated_data['pub_time'],
            category=validated_data['post_category'],
            publisher_id=validated_data['publisher_id']
        )
        book_obj.authors.add(*validated_data['author_list'])
        return book_obj

    def update(self, instance, validated_data):
        # instance为需要更新的对象
        instance.title = validated_data.get('title', instance.title)
        instance.pub_time = validated_data.get('pub_time', instance.pub_time)
        instance.category = validated_data.get('post_category', instance.category)
        instance.publisher_id = validated_data.get('publisher_id', instance.publisher_id)
        if validated_data.get('author_list'):
            instance.authors.set(validated_data['author_list'])
        instance.save()
        return instance
    # 参数校验,与Django中的form校验一样    
    def validate_title(self, value):    
        # 单个字段校验;value就是title的值
        if 'python' not in value.lower():
            raise serializers.ValidationError('标题必须包含python')
        return value

    def validate(self, attrs):
        # 多个字段校验;attrs是个字典,包含前端传递过来的所有字段
        if 'python' in attrs['title'].lower() and attrs['post_category'] == 1:
            return attrs
        raise serializers.ValidationError('参数错误')

自定义数据校验:

def my_validate(value)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值