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

 

posted @ 2020-02-19 21:35  y0um  阅读(455)  评论(0编辑  收藏  举报

新人优惠服务器