1. 程式人生 > 實用技巧 >Python學習————序列化器(複習)

Python學習————序列化器(複習)

序列化器

序列化器可以把模型物件轉換成字典,經過response以後程式設計json字串

反序列化是把客戶端發過來的資料經過request之後變成字典,序列化器可以把字典轉換成模型,

反序列化可以完成資料校驗功能

from rest_framework import serializers

# 宣告序列化器,所有的序列化器都要直接或者間接繼承於 Serializer
# 其中,ModelSerializer是Serializer的子類,ModelSerializer在Serializer的基礎上進行了程式碼簡化
class StudentSerializer(serializers.Serializer):
    """學生資訊序列化器"""
    # 1. 需要進行資料轉換的欄位
    id = serializers.IntegerField()
    name = serializers.CharField()
    age = serializers.IntegerField()
    sex = serializers.BooleanField()
    description = serializers.CharField()

    # 2. 如果序列化器整合的是ModelSerializer,則需要宣告呼叫的模型資訊

    # 3. 驗證程式碼

    # 4. 編寫新增和更新模型的程式碼

常用欄位型別

欄位 欄位構造方式
BooleanField BooleanField()
NullBooleanField NullBooleanField()
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正則欄位,驗證正則模式 [a-zA-Z0-9-]+
URLField URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField UUIDField(format=’hex_verbose’) format: 1) 'hex_verbose'"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex'"5ce0e9a55ffa654bcee01238041fb31a"
3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
IPAddressField IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
IntegerField IntegerField(max_value=None, min_value=None)
FloatField FloatField(max_value=None, min_value=None)
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位數 decimal_palces: 小數點位置
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationField DurationField()
ChoiceField ChoiceField(choices) choices與Django的用法相同
MultipleChoiceField MultipleChoiceField(choices)
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

選項引數:

引數名稱 作用
max_length 最大長度
min_lenght 最小長度
allow_blank 是否允許為空
trim_whitespace 是否截斷空白字元
max_value 最小值
min_value 最大值

通用引數:

引數名稱 說明
read_only 表明該欄位僅用於序列化輸出,預設False
write_only 表明該欄位僅用於反序列化輸入,預設False
required 表明該欄位在反序列化時必須輸入,預設True
default 反序列化時使用的預設值
allow_null 表明該欄位是否允許傳入None,預設False
validators 該欄位使用的驗證器
error_messages 包含錯誤編號與錯誤資訊的字典
label 用於HTML展示API頁面時,顯示的欄位名稱
help_text 用於HTML展示API頁面時,顯示的欄位幫助提示資訊

建立Serializer物件

定義好Serializer類後,就可以建立Serializer物件了。

Serializer的構造方法為:

Serializer(instance=None, data=empty, **kwarg)

說明:

1)用於序列化時,將模型類物件傳入instance引數

2)用於反序列化時,將要被反序列化的資料傳入data引數

3)除了instance和data引數外,在構造Serializer物件時,還可通過context引數額外新增資料,如

serializer = AccountSerializer(account, context={'request': request})

通過context引數附加的資料,可以通過Serializer物件的context屬性獲取。

1. 使用序列化器的時候一定要注意,序列化器聲明瞭以後,不會自動執行,需要我們在檢視中進行呼叫才可以。

2. 序列化器無法直接接收資料,需要我們在檢視中建立序列化器物件時把使用的資料傳遞過來。

3. 序列化器的欄位宣告類似於我們前面使用過的表單系統。

4. 開發restful api時,序列化器會幫我們把模型資料轉換成字典.

5. drf提供的檢視會幫我們把字典轉換成json,或者把客戶端傳送過來的資料轉換字典.

序列化器的使用

序列化器的使用分兩個階段:

  1. 在客戶端請求時,使用序列化器可以完成對資料的反序列化。
  2. 在伺服器響應時,使用序列化器可以完成對資料的序列化。

基本使用

1) 先查詢出一個學生物件

from students.models import Student

student = Student.objects.get(id=3)

2) 構造序列化器物件

from .serializers import StudentSerializer

serializer = StudentSerializer(instance=student)

3)獲取序列化資料

通過data屬性可以獲取序列化後的資料

serializer.data
# {'id': 4, 'name': '小張', 'age': 18, 'sex': True, 'description': '猴賽雷'}

完整檢視程式碼:

from django.views import View
from students.models import Student
from .serializers import StudentSerializer
from django.http.response import JsonResponse
class StudentView(View):
    """使用序列化器序列化轉換單個模型資料"""
    def get(self,request,pk):
        # 獲取資料
        student = Student.objects.get(pk=pk)
        # 資料轉換[序列化過程]
        serializer = StudentSerializer(instance=student)
        print(serializer.data)
        # 響應資料
        return JsonResponse(serializer.data)

高階用法

#source和serializers.SerializerMethodField()的用法
# models.py
from django.db import models

class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish",on_delete=models.CASCADE,null=True)
    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
# ser.py
from rest_framework import serializers
from app01.models import Book
class BookSerializers(serializers.Serializer):
    id=serializers.CharField(read_only=True)
    title=serializers.CharField(max_length=32)
    price=serializers.IntegerField()
    pub_date=serializers.DateField()
    # publish=serializers.CharField(source="publish.name",read_only=True)
    publish=serializers.CharField(source="publish.name",default='xxx')
    #authors=serializers.CharField(source="authors.all")
    authors=serializers.SerializerMethodField(read_only=True)
    def get_authors(self,obj):
        temp=[]
        for author in obj.authors.all():
            temp.append(author.name)
        return temp

    def create(self, validated_data):
        print(validated_data)
        publish_id=validated_data.get('publish').get('name')
        print(publish_id)
        del validated_data['publish']
        return Book.objects.create(publish_id=publish_id,**validated_data)

    def update(self, instance, validated_data):
        print(validated_data.get('aa'))
        instance.title = validated_data.get('title', instance.title)
        instance.price = validated_data.get('price', instance.price)
        instance.pub_date = validated_data.get('pub_date', instance.pub_date)
        print(validated_data.get('publish', instance.publish))
        instance.publish_id = validated_data.get('publish', instance.publish).get('name')
        instance.save()
        return instance
# views.py
from django.shortcuts import render,HttpResponse
from app01 import models

from django.http import HttpRequest

from rest_framework.views import APIView
from app01.models import Book
from rest_framework.response import Response
from app01.ser import BookSerializers
class BookViewSet(APIView):

    def get(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        # 序列化方式3:
        bs=BookSerializers(book_list,many=True)     #many=True代表有多條資料,如果只有一條資料,many=False
        return Response(bs.data)
    def post(self,request,*args,**kwargs):

        bs=BookSerializers(data=request.data)
        bs.is_valid(raise_exception=True)
        # print(bs.validated_data)
        bs.save()
        return Response(bs.data)

class BookDetailView(APIView):
    def get(self,request,pk):
        book_obj=models.Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,many=False)
        return Response(bs.data)
    def put(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()

        bs=BookSerializers(instance=book_obj,data=request.data,partial=True)
        if bs.is_valid():
            bs.save(aa="lqz") # update
            return Response(bs.data)
        else:
            return Response(bs.errors)
    def delete(self,request,pk):
        models.Book.objects.filter(pk=pk).delete()

        return Response("")
# urls.py
from django.contrib import admin
from django.urls import path,re_path
from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookViewSet.as_view()),
    re_path('books/(?P<pk>\d+)/', views.BookDetailView.as_view()),
]

注意:

source 如果是欄位,會顯示欄位,如果是方法,會執行方法,不用加括號(authors=serializers.CharField(source=’authors.all’))

如在模型中定義一個方法,直接可以在在source指定執行

class UserInfo(models.Model):
    user_type_choices = (
        (1,'普通使用者'),
        (2,'VIP'),
        (3,'SVIP'),
    )
    user_type = models.IntegerField(choices=user_type_choices)

    username = models.CharField(max_length=32,unique=True)
    password = models.CharField(max_length=64)


#檢視
ret=models.UserInfo.objects.filter(pk=1).first()
aa=ret.get_user_type_display()

#serializer
xx=serializers.CharField(source='get_user_type_display')