zoukankan      html  css  js  c++  java
  • rest-framework框架之序列化

    rest-framework框架之序列化

    开发 API 接口最重要的工作就是将代码片段的输出序列化和反序列化为类似于 json 的表示形式。

    在 rest-framework 中,通过声明与 Django 中 forms 非常类似的序列化器(serializers)来实现。

    用到的 models

    from django.db import models
    
    
    # Create your models here.
    
    
    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.IntegerField()
        pub_date = models.DateField()
        publish = models.ForeignKey("Publish")
        authors = models.ManyToManyField("Author")
    
        def __str__(self):
            return self.title
    
    
    class Publish(models.Model):
        name = models.CharField(max_length=32)
        email = models.EmailField()
    
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
        def __str__(self):
            return self.name
    
    

    使用 Serializer

    Serializer 的学习可以类比 Django 中的 form 。它们都有 CharField ,IntegerField 等。

    数据表中的普通字段用 CharField ,IntegerField 等,一对多用 CharField ,里面加上 source 指向要对应的字段。多对多用 SerializerMethodField ,并且自定义一个名为 get_多对多字段名 的函数,此时该多对多字段的值取决于这个函数的返回值。

    from app01.models import *
    from rest_framework import serializers
    
    
    class BookSerializers(serializers.Serializer):
        title = serializers.CharField(max_length=32)
        price = serializers.IntegerField()
        pub_date = serializers.DateField()
        # 一对多用CharField,里面加上source
        publish = serializers.CharField(source="publish.name")
        # 多对多用SerializerMethodField
        authors = serializers.SerializerMethodField()
    
        # 此时authors值取决于下面函数的返回值
        def get_authors(self, obj):
            authors_temp = []
            for authors_obj in obj.authors.all():
                authors_temp.append(authors_obj.name)
    
            return ",".join(authors_temp)
    
    

    使用 ModelSerializer

    ModelSerializer 可以类比成 Django 中的 ModelForm 它实现的功能与 Serializer 一样,只是代码量更少,功能更多。

    普通字段

    通过 Meta 类将普通字段转成 Serializer 类中的各种字段。其中, model 绑定的数据表模型,fields 绑定要转化的字段,"__all__" 表示要将所有字段都转成相应的类型。

    class PublishModelSerializers(serializers.ModelSerializer):
        class Meta:
            model = Publish
            fields = "__all__"
    
    

    特殊字段

    特殊字段可以自己添加,和 Serializer 一样,一对多字段用 CharField,里面加上 source ,多对多用 SerializerMethodField ,特殊字段依然可以用 get_字段名 来返回该字段的值。

    注意:存在定制字段,需要改写 create 方法。

    class BookModelSerializers(serializers.ModelSerializer):
        # 默认将普通字段转化
        class Meta:
            model = Book
            fields = "__all__"
    
        # 特殊字段可以自己添加
        # 一对多用CharField,里面加上source
        publish = serializers.CharField(source="publish.name")
        publish = serializers.CharField(source="publish.pk")
        # 多对多用SerializerMethodField
        authors = serializers.SerializerMethodField()
        
        # 此时authors值取决于下面函数的返回值
        def get_authors(self, obj):
            authors_temp = []
            for authors_obj in obj.authors.all():
                authors_temp.append(authors_obj.name)
        
            return ",".join(authors_temp)
    
        # 存在定制字段,所以要改写create方法
        # def create(self, validated_data):
        #     print("validated_data", validated_data)
        #     book_obj = Book.objects.create(title=validated_data["title"], price=validated_data["price"], pub_date=validated_data["pub_date"], publish_id=validated_data["publish"]["pk"])
        #     book_obj.authors.add(*validated_data["authors"])
        #
        #     return book_obj
    

    视图部分

    需要用到 rest-framework 中的 APIView 类。

    对每个数据表模型建立相应的视图类,并在视图类中通过不同的方法来接受前端以不同方法发来的数据。

    from rest_framework.views import APIView
    from .serializer import *
    
    
    # Create your views here.
    class BookViewSet(APIView):
        def get(self, request, *args, **kwargs):
            ...
        
        def post(self, request, *args, **kwargs):
            ...
            
        def put(self, request, *args, **kwargs):
            ...
            
        def patch(self, request, *args, **kwargs):
            ...
    

    序列化方法一

    使用 Django 中的 model_to_dict 。

    book_list = Book.objects.all()
    from django.forms.models import model_to_dict
    import json
    data = []
    for obj in book_list:
        data.append(model_to_dict(obj))
    return HttpResponse(json.dumps(data))
    

    序列化方法二

    使用 Serializer 将数据转成 json 数据。

    data = serializers.serialize("json", book_list)
    return HttpResponse(data)
    

    序列化方法三

    直接通过 Serializer 或者 ModelSerializer 来返回。

    bs = BookSerializers(book_list, many=True)
    bs = BookModelSerializers(book_list, many=True)
    
    # 超链接时需要增加参数
    bs = BookModelSerializers(book_list, many=True, context={'request': request})
    return Response(bs.data)
    

    提交 post 请求

    与 Django 中的 ModelForm 类似,ModelSerializer 也有 is_valid 函数来判断验证是否通过, save 函数来讲数据保存到数据库中。

        def post(self, request, *args, **kwargs):
            bs = BookSerializers(data=request.data, many=False)
            request.data:post的数据
            bs = BookModelSerializers(data=request.data, many=False)
    
            # 超链接时需要增加参数
            bs = BookModelSerializers(data=request.data, many=False, context={'request': request})
    
            if bs.is_valid():
                bs.save()
                return Response(bs.data)
            else:
                return HttpResponse(bs.errors)
    

    单条数据的请求

    单条数据与之前的区别在于多传过来一个单条数据的 ID ,通过该 ID 值进行筛选工作。

    class PublishViewSet(APIView):
    
        def get(self, request, *args, **kwargs):
            publish_list = Publish.objects.all()
            ps = PublishModelSerializers(publish_list, many=True)
    
            return Response(ps.data)
    
        def post(self, request):
            ps = PublishModelSerializers(data=request.data, many=False)
    
            if ps.is_valid():
                print(ps.validated_data)
                ps.save()
                return Response(ps.data)
            else:
                return Response(ps.error)
    
    

    超链接 API

    有时,想让该字段的输出值为超链接,这样也是可以实现的。需要将该字段设置为
    HyperlinkedIdentityField 类型,其中 view_name 为在 urls.py 中设置的视图名, lookup_field 绑定数据表模型的 ID , lookup_url_kwarg 绑定为主键。

    class BookModelSerializers(serializers.ModelSerializer):
        # 默认将普通字段转化
        class Meta:
            model = Book
            fields = "__all__"
    
        # 定制url
        publish = serializers.HyperlinkedIdentityField(
            view_name="detailpublish",
            lookup_field="publish_id",
            lookup_url_kwarg="pk"
        )
    

    而包含超链接的字段进行实例化时,需要添加相应的参数:

    bs = BookModelSerializers(book_list, many=True, context={'request': request})
    

    urls 部分

    对于视图类,只需要在 URL 中调用 as_view 函数即可。

    注意:

    1. 整体数据和单条数据的操作不能用同一个视图类。
    2. 如果有超链接,需要给每个 URL 都加上 name 属性。
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^books/$', views.BookViewSet.as_view(), name="book"),
        url(r'^publishes/$', views.PublishViewSet.as_view(), name="publish"),
        url(r'^publishes/(?P<pk>d+)/$', views.PublishDetailView.as_view(), name="detailpublish"),
        url(r'^authors/$', views.AuthorViewSet.as_view(), name="author"),
        url(r'^books/(d+)/$', views.BookDetailView.as_view(), name="detailbook"),
    ]
    

  • 相关阅读:
    Javascript的二进制数据处理学习 ——nodejs环境和浏览器环境分别分析
    ISO日期格式标准,浏览器到服务器到mysql中的时区
    开始学nodejs —— 调试篇
    TCP三次握手的正确使用姿势
    详解Javascript中正则表达式的使用
    浏览器HTTP缓存原理分析
    seajs3.0.0源码分析记录
    用spm2构建seajs项目的过程
    IIS7禁用单个静态文件的缓存配置方法
    jsp之EL表达式
  • 原文地址:https://www.cnblogs.com/banshaohuan/p/10269264.html
Copyright © 2011-2022 走看看