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("")

~>.<~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM