serializer的使用及DRF的解析器和序列化組件

原生serializer的使用

from django.core.serializers import serialize

class StudentView(APIView):

    def get(self, request):
       
        origin_students = Student.objects.all()
        serialized_students = serialize("json", origin_students)

        return HttpResponse(serialized_students)

DRF解析器組件

使用:html

#1. 引入模塊

from rest_framework.views import APIView

#2. 繼承APIView

class LoginView(APIView):
    parser_classes = [FormParser]

    def get(self, request):
        return render(request, 'parserver/login.html')

# .3. 直接request.data就能夠獲取json數據

    def post(self, request):
        # request是被drf封裝的新對象,基於django的request
        # request.data是一個property,用於對數據進行校驗
        # request.data最後會找到self.parser_classes中的解析器
        # 來實現對數據進行解析
        
        print(request.data)  # {'username': 'alex', 'password': 123}

        return JsonResponse({"status_code": 200, "code": "OK"})

 解釋器組件源碼流程 

 

序列化組件

定義幾個model前端

from django.db import models

# Create your models here.


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


class Book(models.Model):
    title = models.CharField(max_length=32)
    publishDate = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish = models.ForeignKey(to="Publish", to_field="nid", on_delete=models.CASCADE)
    authors = models.ManyToManyField(to="Author")

    def __str__(self):
        return self.title

  

設計url,請求接口

GET接口python

url:git

from django.urls import re_path

from serializers import views

urlpatterns = [
    re_path(r'books/$', views.BookView.as_view())
]

 新建一個名爲app_serializers.py的模塊,將全部的序列化的使用集中在這個模塊裏面,對程序進行解耦:django

from rest_framework import serializers

from .models import Book
#1.定義序列化類 class BookSeriazlizer(seriazlizers.Serializer):
  #2.定義須要返回的字段(字段類型能夠與model中的類型不一致,參數也能夠調整),
  字段名稱必須與model中的一致
  title = serializers.CharField(max_length=128)  
  publish_date = serializers.DateTimeField()
 price = serializers.DecimalField(max_digits=5, decimal_places=2) publish = serializers.CharField(max_length=32) authors = serializers.CharField(max_length=32) 

 視圖類,使用序列化組件 json

from rest_framework.views import APIView
from rest_framework.response import Response

from .models import Book
from .app_serializer import BookSerializer


class BookView(APIView):
    
    def get(self,request):
#3. GET接口邏輯中,獲取QuerySet origin_books = Book.objects.all()
#4.開始序列化 ,many默認爲False,若返回的數據是個多個對象集合,需改成True serialized_books = BookSerializer(origin_books,many=True) return Response(serialized_books.data)

下面是經過POSTMAN請求該接口後的返回的測試數據,除ManyToManyField字段不是想要的外,其餘的都沒有任何問題: app

[
    {
        "title": "Python入門",
        "publishDate": null,
        "price": "119.00",
        "publish": "浙江大學出版社",
        "authors": "serializers.Author.None"
    },
    {
        "title": "Python進階",
        "publishDate": null,
        "price": "128.00",
        "publish": "清華大學出版社",
        "authors": "serializers.Author.None"
    }
]

  

若當字段定義爲多個參數時,好比authors.all,取出來的結果將是一個querset,對前端來書,這樣的數據不太友好,稍微改進下post

class BookSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=32)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    publishDate = serializers.DateField()
    publish = serializers.CharField()
    publish_name = serializers.CharField(max_length=32, read_only=True, source='publish.name')
    publish_email = serializers.CharField(max_length=32, read_only=True, source='publish.email')
    # authors = serializers.CharField(max_length=32, source='authors.all')
    authors_list = serializers.SerializerMethodField()

    def get_authors_list(self, authors_obj):
        authors = list()
        for author in authors_obj.authors.all():
            authors.append(author.name)

        return authors




# 注:get_必須與字段名稱一致,不然會報錯

 

POST接口設計

def post(self, request):
        verified_data = BookSerializer(data=request.data)

        if verified_data.is_valid():
            book = verified_data.save()
            # 可寫字段經過序列化添加成功以後須要手動添加只讀字段
            authors = Author.objects.filter(nid__in=request.data['authors'])
            book.authors.add(*authors)

            return Response(verified_data.data)
        else:
            return Response(verified_data.errors)

  多對多字段一樣須要本身手動來獲取測試

def get_authors_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):
        # {'title': 'Python666', 'price': Decimal('66.00'), 'publish': '2'}
        validated_data['publish_id'] = validated_data.pop('publish')
        book = 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

  

感受仍是有點麻煩,若字段不少,寫序列化也是一種負擔,更加簡單的方式以下:url

# 繼承ModelSerializer

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book

        fields = ('title',
                  'price',
                  'publish',
                  'authors',
                  'author_list',
                  'publish_name',
                  'publish_city'
                  )
        extra_kwargs = {
            'publish': {'write_only': True},
            'authors': {'write_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_list = serializers.SerializerMethodField()

    def get_author_list(self, book_obj):
        # 拿到queryset開始循環 [{}, {}, {}, {}]
        authors = list()

        for author in book_obj.authors.all():
            authors.append(author.name)

        return authors

  詳細步驟:

  • 繼承ModelSerializer:再也不繼承Serializer
  • 添加extra_kwargs類變量:extra_kwargs = {‘publish’: {‘write_only’: True}}
相關文章
相關標籤/搜索