zoukankan      html  css  js  c++  java
  • Django Rest Framework 序列化接口(GET与POST)设计 (前期版)!

    定义序列化器(本质就是一个类),一般包括模型类的字段,有自己的字段类型规则。实现了序列化器后,就可以创建序列化对象以及查询集进行序列化操作,通过序列化对象.data来获取数据(不用自己构造字典,再返回Json数据)

    创建一个django项目;

    创建一个app,且名字为:books

     1 INSTALLED_APPS = [
     2     'django.contrib.admin',
     3     'django.contrib.auth',
     4     'django.contrib.contenttypes',
     5     'django.contrib.sessions',
     6     'django.contrib.messages',
     7     'django.contrib.staticfiles',
     8     'books',
     9     'rest_framework'
    10 ]
    settings.py
    from django.contrib import admin
    from django.urls import path
    from books import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('book/',views.BookView.as_view())
    ]
    urls.py
    from django.shortcuts import render, HttpResponse
    from . import models
    
    # 1.原生django序列化组件使用
    from django.views import View
    from django.core.serializers import serialize
    # 1.Django原生序列化的使用
    # class BookView(View):
    #     def get(self, request):
    #         # 获取queryset
    #         book_list = Book.objects.all()
    #         # 对queryset进行序列化
    #         serialize_data = serialize('json', book_list)
    #         # 返回序列化后的数据
    #         return HttpResponse(serialize_data)
    
    
    # 2.1-DRF序列化组件使用
    from rest_framework.views import APIView
    from rest_framework.response import Response
    # 在应用下新建一个文件:serizlizer.py 用来写相关需要序列化的数据
    # 导入serizlizer.py文件下的:BookSerizlizer类
    from .serizlizer import BookSerizlizer
    
    
    class BookView(APIView):
        def get(self, request):
            # 拿到书的对象数据
            book_obj = models.Book.objects.all()
            # 创造一个序列化器,传入书对象数据。
            serialized_data = BookSerizlizer(book_obj, many=True)
            # 返回DRF序列化后的数据.最后需要点data才能拿到结果
            return Response(serialized_data.data)
    
        # 访问127.0.0.1:8000/books/==>以下为页面拿到的数据(authors字段不正常,
        # 因为authors在数据库与book表是多对多字段,
        # 所以在serizlizer.py里面def一个方法来获取这项数据)
        '''    [
        {
            "nid": "1",
            "title": "python初级",
            "price": "188.00",
            "publish": "清华大学出版社",
            "authors": "serializer.Author.None"
        },
        {
            "nid": "2", 
            "title": "python中级",
            "price": "78.00",
            "publish": "清华大学出版社",
            "authors": "serializer.Author.None"
        },   
              ]
        '''
    
        def post(self, request):
            '''通过序列化组件进行post接口(提交一条数据)设计,步骤如下:
        - 定义post方法:在视图类中定义post方法;
        - 开始序列化:通过上面定义的序列化类,创建一个序列化对象,传入参数data=request.data(application/json)数据;
        - 校验数据:通过实例对象的is_valid()方法,对请求数据的合法性进行校验;
        - 保存数据:调用save()方法,将数据插入数据库;
        - 插入数据到多对多关系表:如果有多对多字段,手动插入数据到多对多关系表;
        - 返回:将插入的对象返回;
          '''
            serialized_data = BookSerizlizer(data=request.data)
            if serialized_data.is_valid():
                book = serialized_data.save()
                # 手动绑定多对多关系,也可以放到create方法中去
                authors = models.Author.objects.filter(nid__in=request.data['authors'])
                book.authors.add(*authors)
                return Response(serialized_data.data)
            else:
                return Response(serialized_data.errors)
    
    '''分析:上面这种方法有两个问题:一个是需要手动插入数据(写序列化类中写create方法),
    另一个是如果字段很多,写序列化类的字段也会变成一种负担,那么有没有更简单的方式呢?当然,
    那就是用ModelSerializer!所以我们需要修改一下serializer.py中的代码'''
    views.py
    from django.db import models
    
    # Create your models here.
    
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish = models.ForeignKey(to='Publish', related_name='book', on_delete=models.CASCADE)
        authors = models.ManyToManyField(to='Author')
    
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
        email = models.EmailField()
    
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
        def __str__(self):
            return self.name
    mdoels.py
    # 2.1-导入序列化模块.创造一个序列化数据的类
    from rest_framework import serializers
    
    #一版本的序列化类
    # class BookSerizlizer(serializers.Serializer):
    #     nid = serializers.CharField(max_length=32)
    #     title = serializers.CharField(max_length=128)
    #     price = serializers.IntegerField()
    #     publish = serializers.CharField(max_length=32)
    #     # authors = serializers.CharField(max_length=32)#authors为多对多字段,应该使用下面的方法
    #     authors = serializers.SerializerMethodField()
    #
    #     # 定义一个方法获取多对多字段数据,注意:get_必须与字段字段名称一致,否则报错。,并传入一个book对象
    #     def get_authors(self, book_obj):
    #         authors = []
    #         # book_obj.authors.all()拿到每本书对应的作者(比如:models.Book.objects.first().authors.all()拿到第一本书的作者)
    #         for author in book_obj.authors.all():
    #             # 把作者的名字添加进去,(author.name)
    #             authors.append(author.name)
    #         return authors
    
    #关于POST接口需要重新写一下BookSerizlizer类
    '''注意:因为多对多关系字段是我们自定义的,而且必须这样定义,返回的数据才有意义,
    而用户插入数据的时候,无法找到这个字段类型SerializerMethodField,
    所以,序列化类不能帮我们插入数据到多对多表,我们必须手动插入数据,!!!以上序列化类注释不用了!!!因此序列化类要做如下修改:'''
    #二版本序列化类
    # from .models import Book
    #
    # class BookSerizlizer(serializers.Serializer):
    #     # nid字段只需要传给客户端,用户提交不需要id,所以read_only=True
    #     nid = serializers.CharField(read_only=True, max_length=32)
    #     title = serializers.CharField(max_length=128)
    #     price  = serializers.DecimalField(max_digits=5, decimal_places=2)
    #     publish = serializers.CharField(max_length=32)
    #     # SerializerMethodField默认read_only=True
    #     authors = serializers.SerializerMethodField()
    #
    #         # 定义一个方法获取多对多字段数据,注意:get_必须与字段字段名称一致,否则报错。,并传入一个book对象
    #     def get_authors(self, book_obj):
    #         authors = []
    #         # book_obj.authors.all()拿到每本书对应的作者(比如:models.Book.objects.first().authors.all()拿到第一本书的作者)
    #         for author in book_obj.authors.all():
    #             # 把作者的名字添加进去,(author.name)
    #             authors.append(author.name)
    #         return authors
    #
    #     # 必须手动插入数据,因此post方法提交数据必须有create方法!
    #     def create(self, validated_data):
    #         print(validated_data) # validated_data为过滤之后的数据
    #         validated_data['publish_id'] = validated_data.pop('publish')
    #         book = Book.objects.create(**validated_data)
    #
    #         return book
    
    #三版本序列化类
    from . import models
    #使用ModelSerializer,post方法就不再依赖create方法
    class BookSerizlizer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = (
                'title',
                'price',
                'publish',
                'authors',
                'author_list',
                'pubName',
                'pubCity'
            )
            extra_kwargs = {
                'publish':{'write_only':True},
                'authors':{'write_only':True}
            }
    
        pubName = serializers.CharField(max_length=32, read_only=True, source='publish.name')
        pubCity = serializers.CharField(max_length=32, read_only=True, source='publish.city')
    
        # 多对多字段
        author_list = serializers.SerializerMethodField()
    
        def get_author_list(self, book_obj):
            authors = list()
    
            for author in book_obj.authors.all():
                authors.append(author.name)
    
            return authors
    serizlizer.py
  • 相关阅读:
    [ SDOI 2006 ] 保安站岗
    [ TJOI 2012 ] 防御
    [ ZJOI 2012 ] 灾难
    [ HNOI 2008 ] 玩具装箱
    「UER#2」信息的交换
    「UR#5」怎样跑得更快
    「UR#6」懒癌
    清华集训2014 做题记录
    「UR#5」怎样更有力气
    弦图及区间图学习笔记
  • 原文地址:https://www.cnblogs.com/cou1d/p/12333340.html
Copyright © 2011-2022 走看看