Django用rest_framework里的serializers.Serializer序列化

序列化组件的使用及接口设计

  1. 请求接口设计get请求(restapi规范)

      GET						127.0.0.1:8000/books/			# 获取所有数据, 返回值:[{}, {}, {}]
      GET						127.0.0.1:8000/books/{id}       # 获取一条数据, 返回值:{}
      POST					    127.0.0.1:8000/books/			# 新增一条数据, 返回值:{}
      PUT						127.0.0.1:8000/books/{id}       # 修改一条数据, 返回值:{}
      DELETE                    127.0.0.1:8000/books/{id}       # 删除一条数据, 返回值: 空对象
    
  2. 创建model.py

    1. python manage.py makemigrations

    2. python manage.py migrate

    3. urls.py

    4. views.py

    5. 开始使用序列化

      1. 导入模块 from rest_framework import serializers

      2. 建立一个序列化类

        class BookSerializer(serializers.Serializer):
          	字段可以自定义
        
      3. 获取queryset

        origin_data = Book.objects.all()
        
      4. 开始序列化

        serialized_data = BookSerializer(origin_data, many=True )
        
      5. 序列化后的数据, 返回给客户端

        return Response(serialized_data.data)
        

案例GET请求

  1. 创建模型类

    from django.db import models
    
    from datetime import datetime
    # from django.contrib.auth.models import AbstractUser
    
    
    class AuthorInfo(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者名称")
        age = models.IntegerField(verbose_name="作者年龄")
    
        class Meta:
            db_table = "db_author_info"
            verbose_name = "作者信息"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class PublishInfo(models.Model):
        name = models.CharField(max_length=32, verbose_name="出版社名称")
        city = models.CharField(max_length=32, verbose_name="出版社所在城市")
        email = models.EmailField(verbose_name="出版社邮箱")
    
        class Meta:
            db_table = "db_publish_info"
            verbose_name = "出版社信息"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class BookInfo(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
        publishDate = models.DateField(default=datetime.now, verbose_name="出版日期")
    
        # max_digits小数位加整数位多少长度 decimal_places小数位长度为2
        price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="图书价格")
        
        # on_delete
        # CASCADE:这就是默认的选项,级联删除,你无需显性指定它。
    		# PROTECT: 保护模式,如果采用该选项,删除的时候,会抛出ProtectedError错误。
    		# SET_NULL: 置空模式,删除的时候,外键字段被设置为空,前提就是blank=True, null=True,定义该字段的时候,允许为空。
    		# SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值,所以定义外键的时候注意加上一个默认值。
    		# SET(): 自定义一个值,该值当然只能是对应的实体了
        publish = models.ForeignKey(PublishInfo, related_name="book", related_query_name="book_query", on_delete=models.CASCADE, verbose_name="出版社")
        # ManyToManyField多对多
        authors = models.ManyToManyField(AuthorInfo, verbose_name="图书作者")
    
        class Meta:
            db_table = "db_book_info"
            verbose_name = "图书信息"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.title
    
    
  2. 创建urls.py

    from django.urls import re_path
    from .views import BookView
    
    urlpatterns = [
      	# restapi风格定制路由
        re_path(r"^books/$", BookView.as_view()),
    ]
    
    
  3. 创建views.py

    1. 导入模块

      # 第一步: 导入模块
      from rest_framework import serializers
      
    2. 建立序列化类

      # 第二步: 创建序列化类, 字段类型不一定要跟model的字段一致
      class BookSerializer(serializers.Serializer):
          title = serializers.CharField(max_length=128)
          publishDate = serializers.DateField(default=datetime.now)
          price = serializers.DecimalField(max_digits=5, decimal_places=2)
      
          # 序列化没有外键(ForeignKey)和多对多(ManyToManyField)
          # 显示出来的是id值, 意义不大可以不写
        	# 外键字段
          publish = serializers.CharField()
          # 外键字段显示__str__方法的返回值, 但是你写了source那么source指定的值覆盖掉__str__的值
          # (注意source指定的值必须是模型类里面的)
          # read_only=True 读的时候有它, 写的时候不需要它
          publish_name = serializers.CharField(max_length=32, read_only=True, source="publish.name")
          publish_city = serializers.CharField(max_length=32, read_only=True, source="publish.city")
      
          # author = serializers.CharField(max_length=32)
          # 多对多字段需要自己手动获取数据, SerializerMethodField(), 他就会自动去找一个(get_固定格式)get_当前字段(authors)
          # SerializerMethodField()默认是自读字段, 写的时候是不会检查的,  它源码里写了read_only=True
          authors = serializers.SerializerMethodField()
      
          # 方法名必须是get_ 加上字段上面的多对多字段的名
          # 固定传一个当前表的对象
          def get_authors(self, book_obj):
              author_list = []
              # book_obj.authors.all() 获取所有author对象
              for author in book_obj.authors.all():
               author_list.append(author.name)
              # 返回的值就是authors的值
           return author_list
      
      
    3. 获取queryset/开始序列化/序列化后的数据, 返回给客户端

      from rest_framework.views import APIView
      # Response返回序列化对象
      from rest_framework.response import Response
      
      from .models import BookInfo, PublishInfo, AuthorInfo
      from .app_serializers import BookSerializer
      
      
      class BookView(APIView):
          def get(self, request):
              # 第三步: 获取queryset
              origin_data = BookInfo.objects.all()
      
              # 第四步: 开始序列化
              # 当序列化多条数据时 要加上many=True
              serialized_data = BookSerializer(origin_data, many=True)
      				
              # 返回序列化对象
              # 记住序列化的值在data属性里
              # 所以这里用serialized_data.data取序列化的值
              return Response(serialized_data.data)
      
    4. postman效果图
      在这里插入图片描述

    5. 浏览器效果图
      在这里插入图片描述

序列化组件接口设计post请求

  1. 通过序列化组件进行

    GET						127.0.0.1:8000/books/			# 获取所有数据, 返回值:[{}, {}, {}]
    GET						127.0.0.1:8000/books/{id}       # 获取一条数据, 返回值:{}
    POST					127.0.0.1:8000/books/			# 新增一条数据, 返回值:{}
    PUT						127.0.0.1:8000/books/{id}       # 修改一条数据, 返回值:{}
    DELETE                  127.0.0.1:8000/books/{id}       # 删除一条数据, 返回值: 空对象
    
    1. 创建model.py

      1. python manage.py makemigrations
      2. python manage.py migrate
    2. urls.py

    3. views.py

      1. 开始使用序列化

        1. 导入模块 from rest_framework import serializers

        2. 建立一个序列化类

          class BookSerializer(serializers.Serializer):
            	字段可以自定义
          
        3. 获取客户端请求数据

        4. 开始序列化

          verified_data = BookSerializer(data=client_data, many=False)

        5. 写入数据库
          book = verified_data.save()

        6. 序列化后的数据, 返回给客户端

          return Response(serialized_data.data)

案列POST请求

  1. 创建模型类

    from django.db import models
    
    from datetime import datetime
    # from django.contrib.auth.models import AbstractUser
    
    
    class AuthorInfo(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者名称")
        age = models.IntegerField(verbose_name="作者年龄")
    
        class Meta:
            db_table = "db_author_info"
            verbose_name = "作者信息"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class PublishInfo(models.Model):
        name = models.CharField(max_length=32, verbose_name="出版社名称")
        city = models.CharField(max_length=32, verbose_name="出版社所在城市")
        email = models.EmailField(verbose_name="出版社邮箱")
    
        class Meta:
            db_table = "db_publish_info"
            verbose_name = "出版社信息"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class BookInfo(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
        publishDate = models.DateField(default=datetime.now, verbose_name="出版日期")
    
        # max_digits小数位加整数位多少长度 decimal_places小数位长度为2
        price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="图书价格")
        
        # on_delete
        # CASCADE:这就是默认的选项,级联删除,你无需显性指定它。
    	# PROTECT: 保护模式,如果采用该选项,删除的时候,会抛出ProtectedError错误。
    	# SET_NULL: 置空模式,删除的时候,外键字段被设置为空,前提就是blank=True, null=True,定义该字段的时候,允许为空。
    	# SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值,所以定义外键的时候注意加上一个默认值。
    	# SET(): 自定义一个值,该值当然只能是对应的实体了
        publish = models.ForeignKey(PublishInfo, related_name="book", related_query_name="book_query", on_delete=models.CASCADE, verbose_name="出版社")
        # ManyToManyField多对多
        authors = models.ManyToManyField(AuthorInfo, verbose_name="图书作者")
    
        class Meta:
            db_table = "db_book_info"
            verbose_name = "图书信息"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.title
    
    
  2. 创建urls.py

    from django.urls import re_path
    from .views import BookView
    
    urlpatterns = [
      	# restapi风格定制路由
        re_path(r"^books/$", BookView.as_view()),
    ]
    
    
  3. 创建views.py

    1. 导入模块

      # 第一步: 导入模块
      from rest_framework import serializers
      
    2. 建立序列化类, 并且要自定义create方法

      # 第二步: 创建序列化类, 字段类型不一定要跟model的字段一致
      class BookSerializer(serializers.Serializer):
          title = serializers.CharField(max_length=128)
          publishDate = serializers.DateField(default=datetime.now)
          price = serializers.DecimalField(max_digits=5, decimal_places=2)
      
          # 序列化没有外键(ForeignKey)和多对多(ManyToManyField)
          # 显示出来的是id值, 意义不大可以不写
        	# 外键字段
          publish = serializers.CharField()
          # 外键字段显示__str__方法的返回值, 但是你写了source那么source指定的值覆盖掉__str__的值
          # (注意source指定的值必须是模型类里面的)
          # read_only=True 读的时候有它, 写的时候不需要它
          publish_name = serializers.CharField(max_length=32, read_only=True, source="publish.name")
          publish_city = serializers.CharField(max_length=32, read_only=True, source="publish.city")
      
          # author = serializers.CharField(max_length=32)
          # 多对多字段需要自己手动获取数据, SerializerMethodField(), 他就会自动去找一个(get_固定格式)get_当前字段(authors)
          # SerializerMethodField()默认是自读字段, 写的时候是不会检查的,  它源码里写了read_only=True
          authors = serializers.SerializerMethodField()
      
          # 方法名必须是get_ 加上字段上面的多对多字段的名
          # 固定传一个当前表的对象
          def get_authors(self, book_obj):
              author_list = []
              # book_obj.authors.all() 获取所有author对象
              for author in book_obj.authors.all():
                  author_list.append(author.name)
              # 返回的值就是authors的值
              return author_list
            
          def create(self, validated_data):
          	# 把上面所有的字段放在validated_data里面
              # {'price': Decimal('66.00'), 'publishDate': datetime.date(2019, 7, 25), 'title': 'python666', 'publish': '2'}
              print(validated_data)
              validated_data["publish_id"] = validated_data.pop("publish")
              # {'publishDate': datetime.date(2019, 7, 25), 'publish_id': '2', 'title': 'python666', 'price': Decimal('66.00')}
              print(validated_data)
              # **validated_data 字典解析
              # 创建数据库对象并且保存在数据库中, 并把这个对象返回给book
              book = BookInfo.objects.create(**validated_data)
              return book
      
      
    3. 获取数据/开始序列化/序列化后的数据, 返回给客户端

      from rest_framework.views import APIView
      # Response返回序列化对象
      from rest_framework.response import Response
      
      from .models import BookInfo, PublishInfo, AuthorInfo
      from .app_serializers import BookSerializer
      
      
      class BookView(APIView):
          def get(self, request):
              # 第三步: 获取queryset
              origin_data = BookInfo.objects.all()
      
              # 第四步: 开始序列化
              # 当序列化多条数据时 要加上many=True
              serialized_data = BookSerializer(origin_data, many=True)
      				
              # 返回序列化对象
              # 记住序列化的值在data属性里
              # 所以这里用serialized_data.data取序列化的值
              return Response(serialized_data.data)
            
           def post(self, request):
              # 接受前端发送的json数据
              client_data = request.data
      
              # many默认是False, 可以省略不写
              # 开始序列化
              verified_data = BookSerializer(data=client_data, many=False)
              # 判断序列化数据的合法性
              if verified_data.is_valid():
                  # 当执行save()他就会去找create方法, 并且接受create的返回值
                  book = verified_data.save()
                  # 查询出id在request.data这个列表里的对象
                  authors = AuthorInfo.objects.filter(id__in=request.data["authors"])
                  # *authors列表解析
                  # book这个对象下的authors是一个列表把查询出来的authors对象添加到book.authors对象中
                  book.authors.add(*authors)
                  return Response(verified_data.data)
              else:
                  return Response(verified_data.errors)
      
    4. postman效果图
      在这里插入图片描述

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只因为你温柔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值