zoukankan      html  css  js  c++  java
  • DRF Django REST framework 之 序列化(三)

    Django 原生 serializer (序列化)

    1. 导入模块  from django.core.serializers import serialize 
    2. 获取 queryset 
    3. 对 queryset 进行序列化
    4. 将序列化之后的数据,返回给客户端

    首先,设计url, 先只定义GET和POST接口

    from django.urls import path
    
    from DrfOne import views
    
    urlpatterns = [
        path('books/', views.BookView.as_view()),
    ]

    再定义几个models

     1 from django.db import models
     2 
     3 
     4 class Publish(models.Model):
     5     nid = models.AutoField(primary_key=True)
     6     name = models.CharField("出版社名", max_length=32)
     7     address = models.CharField("出版社位置", max_length=32)
     8     email = models.EmailField("邮箱")
     9 
    10     def __str__(self):
    11         return self.name
    12 
    13 
    14 class Author(models.Model):
    15     nid = models.AutoField(primary_key=True)
    16     name = models.CharField("姓名", max_length=31)
    17     age = models.IntegerField("年龄")
    18 
    19     def __str__(self):
    20         return self.name
    21 
    22 
    23 class Book(models.Model):
    24     nid = models.AutoField(primary_key=True)
    25     title = models.CharField("书名", max_length=32)
    26     price = models.DecimalField("价格", max_digits=5, decimal_places=2)
    27     publish = models.ForeignKey(to="Publish", on_delete=models.CASCADE)
    28     authors = models.ManyToManyField(to="Author")
    29 
    30     def __str__(self):
    31         return self.title
    models.py

    使用

    from django.shortcuts import render, HttpResponse
    from rest_framework.views import APIView
    # 1.导入模块
    from django.core.serializers import serialize
    
    
    class CourseView(APIView):
        def get(self, request):
            # 2.获取queryset    
            course_obj = models.Course.objects.all()
            # 3.序列化
            serialized_data = serialize("json", course_obj)
            print(serialized_data)
            # 4.将序列化之后的数据返回
            return HttpResponse(serialized_data)

    序列化组件serializer的使用

    Serializer

    GET接口设计(获取所有数据)

    1. 导入模块
    2. 建立一个序列化类
    3. 获取 queryset 
    4. 开始序列化
    5. 获取序列化后的数据,返回给客户端
    from rest_framework.views import APIView
    # 1.导入模块
    from rest_framework import serializers
    # drf重新封装之后的Response基于TemplateResponse类型,
    # 可以将未处理的内容通过内容协商来决定返回给客户端的正确内容形式
    from rest_framework.response import Response
    
    from DrfOne import models
    
    
    # 2.创建一个序列化类,字段类型不一定要跟models的字段一样
    class BookSerializer(serializers.Serializer):
        # id一般情况不用写
        # nid = serializers.CharField(max_length=32)
        title = serializers.CharField(max_length=32)
        price = serializers.DecimalField(max_digits=5, decimal_places=2)
        # 外键字段,显示__str__方法的返回值
        publish = serializers.CharField()
    
        # 多对多字段, 执行get_字段名 方法,手动获取数据
        author_list = serializers.SerializerMethodField()
    
        def get_author_list(self, book_obj):
            # 第二个参数随意
            author_list = list()
            for author in book_obj.authors.all():
                author_list.append(author.name)
            return author_list
    
    
    class BookView1(APIView):
        def get(self, request):
            # 3.获取queryset
            book_objs = models.Book.objects.all()
            # 4.通过序列化类进行序列化
            serialized_obj = BookSerializer(book_objs, many=True)
            # print(serialized_obj)
    
            # 5.获取序列化之后的数据,返回给客户端
            return Response(serialized_obj.data)

    POST接口设计

    1. 导入模块
    2. 建立一个序列化类
    3. 获取客户端请求数据
    4. 开始序列化
    5. 写入数据库
    6. 将插入的对象返回给客户端

    请注意,因为多对多关系字段是我们自定义的,而且必须这样定义,返回的数据才有意义,而用户插入数据的时候,serializers.Serializer没有实现create,我们必须手动插入数据,就像这样:

    # 1.导入模块
    from rest_framework import serializers
    from rest_framework.views import APIView
    # drf重新封装之后的Response基于TemplateResponse类型,
    # 可以将未处理的内容通过内容协商来决定返回给客户端的正确内容形式
    from rest_framework.response import Response
    
    from DrfOne import models
    
    
    # 2.创建一个序列化类,字段名和字段类型不一定要跟models的字段一样
    class BookSerializer(serializers.Serializer):
        # id一般情况不用写
        # nid = serializers.CharField(max_length=32)
        title = serializers.CharField(max_length=32)
        price = serializers.DecimalField(max_digits=5, decimal_places=2)
        # 外键字段,显示__str__方法的返回值
        publish = serializers.CharField()
        # 仅读字段read_only=True,source是该字段显示出版社地址
        publish_address = serializers.CharField(max_length=32, read_only=True, source="publish.address")
        publish_email = serializers.CharField(max_length=32, read_only=True, source="publish.email")
    
        # 多对多字段, 执行get_字段名 方法,手动获取数据
        author_list = serializers.SerializerMethodField()
    
        def get_author_list(self, book_obj):
            # 第二个参数随意
            author_list = list()
            for author in book_obj.authors.all():
                author_list.append(author.name)
            return author_list
    
        def create(self, validated_data):
            # 创建时调用
            validated_data['publish_id'] = validated_data.pop('publish')
            book = models.Book.objects.create(**validated_data)
            return book
    
        def update(self, instance, validated_data):
            # 更新数据会调用该方法
            instance.title = validated_data.get('title', instance.title)
            instance.publishDate = validated_data.get('publishDate', instance.publishDate)
            instance.price = validated_data.get('price', instance.price)
            instance.publish_id = validated_data.get('publish', instance.publish.nid)
    
            instance.save()
    
            return instance
    
    
    class BookView(APIView):
        def get(self, request):
            pass
    
        def post(self, request):
            # 3.获取客户端的数据
            client_data = request.data
            # 4.序列化,默认many=False单条数据
            verified_data = BookSerializer(data=client_data)
            # 对数据进行验证
            if verified_data.is_valid():
                # 5.写入数据库
                book = verified_data.save()
                authors = models.Author.objects.filter(nid__in=request.data["authors"])
                book.authors.add(*authors)
                # 6.将插入的对象数据返回
                return Response(verified_data.data)
            # 验证失败返回错误信息
            return Response(verified_data.errors)

    从上面可以看出:

    1.  serializers.Serializer 无法插入数据,只能自己实现。
    2. 字段太多,不能自动序列化

    这样就会非常复杂化程序,如果我希望序列化类自动插入数据呢?

    这也就有了 ModelSerializer 

    ModelSerializer

     ModelSerializer  类似于form组件里的 ModelForm 

    from rest_framework import serializers
    from rest_framework.views import APIView
    
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
            extra_kwargs = {
                # 仅写
                "publish": {'write_only': True},
                "authors": {'write_only': True},
            }
    
        publish_name = serializers.CharField(max_length=32, read_only=True, source="publish.name")
        publish_address = serializers.CharField(max_length=32, read_only=True, source="publish.address")
        author_name = serializers.SerializerMethodField()
    
        def get_author_name(self, book_obj):
            author_list = list()
            for author in book_obj.authors.all():
                # 注意列表添加字段,author.name而不是author
                author_list.append(author.name)
            return author_list

    这样看起来简单多了!

    get(单条数据)、put(改)、delete(删) 接口设计

    设计url

    from django.urls import path, re_path
    
    from DrfOne import views
    
    urlpatterns = [
        path('books/', views.BookView.as_view()),
        re_path("books/(d+)/", views.BookFilterView.as_view()),
    ]

    视图设计

    class BookFilterView(APIView):
        def get(self, request, nid):
            # 获取queryset
            book_obj = models.Book.objects.get(pk=nid)
            # 序列化
            serialized_data = BookSerializer(book_obj)
            # 返回数据
            return Response(serialized_data.data)
    
        def put(self, request, nid):
            # 获取queryset
            book_obj = models.Book.objects.get(pk=nid)
            # 序列化, 根据instance是确认是否是更新, many默认为False可以不写
            verified_data = BookSerializer(data=request.data, instance=book_obj, many=False)
            if verified_data.is_valid():
                verified_data.save()
                # 返回数据
                return Response(verified_data.data)
            return Response(verified_data.errors)
    
        def delete(self, request, nid):
            models.Book.objects.get(pk=nid).delete()
    
            return Response("")

    ~>.<~

  • 相关阅读:
    iOS学习-UITextField
    iOS学习-UIButton->Block
    iOS学习-UIButton
    iOS常用技术-微信下标栏
    学习进度表
    学习进度表
    读后感
    我的学习进度表
    调查问卷
    我的学习进度表
  • 原文地址:https://www.cnblogs.com/pungchur/p/12022990.html
Copyright © 2011-2022 走看看