一,Serializer和ModelSerializer


1.REST Framework概述

Django REST framework是一套基於Django的REST框架,是一個用於構建Web API的功能強大且靈活的工具包。

RESTful 簡述

Representational State Transfer(REST),是一種架構樣式,定義了一套用於創建WEB服務的約束。當前WEB開發趨勢就是前端層出不窮,為了保證一個后台同時適用於多個前端,需要一種統一的機制或API,而RESTful API是目前前后端分離的最佳實踐。

為什么需要前后端分離?

  • PC,APP,Pad 等多端適應;
  • SPA開發模式流行(Single Page web Application);
  • 使得前后端開發職責清楚,提高開發效率高;
  • 避免了開發語言和模板語言的高度耦合和開發語言之間的依賴;

RESTful API特點

  • 輕量,直接通過HTTP協議,不需要額外的協議;
  • 面向資源,每一個URL代表一種資源,具有自解釋性;
  • 數據描述簡單,一般通過JSON、xml做數據通信;
  • 客戶端根據不同的請求,通過不同的HTTP方法(get、post、delete、put),對服務器資源進行操作。

為什么要使用Django REST 框架而不是Django?

雖然Django中可以通過DTL(Django Template Language)來實現PC端的顯示,但卻無法支持如Android端、ios端。而且Django只能依賴DTL實現PC端的顯示。

要實現一套后台適應多個前端,就必須使用前后端分離技術,因此就要使用RESTful API,而Django REST框架正是基於Django的RESTful API。

2.安裝Django REST Framework


通過如下命令安裝REST 框架:

pip install djangorestframework


如果沒有安裝Python,則需要安裝Python和Django:

sudo apt-get install python3.6
sudo apt-get install python3-pip
pip install Django

 

3.序列化和反序列化

序列化,是指將復雜的QuerySet和Model類型轉換成Python基本數據類型,從而將這些基本數據類型以JSON的形式響應給客戶端。

反序列化則和序列化相反,是指將Http請求中傳入的JSON數據轉換成復雜的數據類型,從而保存在數據庫中。

在REST Framework中,提供了多個用於序列化操作的類,但常用的也就如下兩個:

  • Serializer:進行序列化基本的類;
  • ModelSerializer:繼承於Serializer,內部實現了通用的序列化邏輯,其中包含了與Model字段對應的字段,可以快速對Model進行序列化。

使用時需要導入對應模塊:

from rest_framework import serializers

  

接下來我們就分別看看這兩個序列化操作的類。

4.Serializer

Serializer進行序列化的基本格式如下:

from rest_framework import serializers

class CommentSerializer(serializers.Serializer):
    # 指定要序列化的字段
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()
    # 用於反序列化時創建一個Model實例
    def create(self, validated_data):
        return Comment(**validated_data)
    # 用於反序列化時更新一個Model實例
    def update(self, instance, validated_data):
       # ...
       instance.email = validated_data.get('email',instance=emial)
       # ...
       return instance

  

接下來我們看看在REST框架中如何對一個Model進行序列化操作。

Step1.創建一個model:

from django.db import models

class Student(models.Model):
    name = models.CharField(max_length=40)
    age = models.IntegerField()
    number = models.IntegerField(unique=True)
    date = models.DateField()

Step2.創建對該Model進行序列化的類:

在app/下創建serializer.py文件

from rest_framework import serializers
from .models import Student

class StudentSerializer(serializers.Serializer):
    # 定義要序列化的字段
    name = serializers.CharField(read_only=True)
    age = serializers.IntegerField(read_only=True)
    number = serializers.IntegerField(read_only=True)
    date = serializers.DateField(read_only=True)

    # 在反序列化時,當save()調用時生成一個Student對象
    def create(self, validated_data):
        # 會將生成的實例保存到數據庫
        return Student.objects.create(**validated_data)

    # 在反序列化時,當save()調用時更新Student對象
    def update(self, instance, validated_data):

        instance.name = validated_data.get('name', instance.name)
        instance.age = validated_data.get('age', instance.age)
        instance.number = validated_data.get('number', instance.number)
        instance.date = validated_data.get('date', instance.date)
        instance.save()  #確保保存在數據庫
        return instance

這個序列化類中有兩部分:

  • 1.定義了要進行序列化的字段;這些字段負責將Python類型轉換成JSON類型,即序列化的過程;
  • 2.定義了當serializer.save()時用於生成Model對象的create()和update()方法,這兩方法負責將JSON類型的數據轉換成Python類型的數據,即反序列化的過程。

整個序列化類的實現就這么簡單,接下來我們還需要對這個序列化類進行測試。

測試Serializer有兩種方式,一種是在Django Shell下進行測試,還有一種就是直接創建一個View,通過http請求進行測試,如果掌握了如何創建view,那么請直接在View中進行吧!

Step3.在Django shell下進行序列化測試


使用python manage.py shell進入Django Shell中:

>>> from Students.models import Student  # 導入對應module
>>> from Students.serializers import StudentSerializer
>>> stu = Student(name='zhangsan',age=21,number=1,date='2018-4-23') #創建一個Model實例
>>> stu.save()   # 將該實例存入數據庫
>>> serializer = StudentSerializer(stu)   #進行序列化
>>> serializer.data  # 查看序列化后的結果
{'name': 'zhangsan', 'age': 21, 'number': 1, 'date': '2018-4-23'}

現在將Student實例轉換成了Python中的dict類型,接下來將dict類型轉換為JSON數據:

>>> from rest_framework.renderers import  JSONRenderer  #JSONRenderer將數據渲染稱JSON格式
>>> content = JSONRenderer().render(serializer.data)
>>> content
b'{"name":"zhangsan","age":21,"number":1,"date":"2018-4-23"}'
>>> 

反序列化類似,第一步是將JSON形式數據轉換為流的形式,並將流數據轉化為python本地數據類型:

>>> from django.utils.six import BytesIO
>>> from rest_framework.parsers import JSONParser
>>> stream = BytesIO(content)  # 將JSON數據轉換為流的形式
>>> data = JSONParser().parse(stream) # JSONParser將解析流中的JSON數據,得到Python的類型數據
>>> data
{'name': 'zhangsan', 'age': 21, 'number': 1, 'date': '2018-4-23'}  # 一個dict類型的數據
>>> 

然后將Python本地類型轉換為實例,保存在數據庫中:

>>> serializer = StudentSerializer(data=data)
>>> serializer.is_valid()  # 驗證是否有效
>>> True
>>> serializer.save()   # 將保存在數據庫中

該例中是序列化了一個Model對象,如果要序列化由Model.objects.all()返回的一個QuerySet實例,在設置serializer時添加一個參數:

>>> serializer = StudentSerializer(Student.objects.all(), many=True)
>>> serializer.data
>>> 

雖然這種方式略顯麻煩,但對於初學者來說,掌握Django shell還是很有用的。
如果對View相關知識了解,那么可以非常方便的在View中通過Http請求進行驗證,如下是通過GET請求和POST請求用於驗證Serializer:

from rest_framework import views
from rest_framework.response import Response
from rest_framework import status
from . import models
from .serializers import StudentSerializer
# Create your views here.

class show(views.APIView):

    def get(self, request):
        """
        get方法處理GET請求
        """
        try:
            Student = models.Student.objects.all()
            # Student是一個QuerySet,而不是一個Model對象,因此需要設置many=True
            serializer = StudentSerializer(Student, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Student.DoesNotExist:
            return Response(serializer.data, status=status.HTTP_404_NOT_FOUND)

    def post(self, request):
        """
        post方法處理POST請求
        """
        # request.data是請求體中經過解析后的數據
        serializer = StudentSerializer(data=request.data)
        if serializer.is_valid(): # 檢驗是否有效
            serializer.save() # 將會調用Serializer中的create(),並保存在數據庫中
            # serializer.data是序列化后的原始數據
            # rest_framework.status中定義了常見返回值,如404,200...
            return Response(serializer.data, status=status.HTTP_201_CREATED)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
ails/80059024 

關於DRF的View相關部分會在之后的文章中詳細總結。

5.Serializer的方法和屬性

1.save()

在調用serializer.save()時,會創建或者更新一個Model實例(調用create()或update()創建),具體根據序列化類的實現而定,如:

# .save() will create a new instance.
serializer = StudentSerializer(data=data)

# .save() will update the existing `comment` instance.
serializer = StudentSerializer(comment, data=data)

2.create()、update()

Serializer中的create()和update()方法用於創建生成一個Model實例,在使用Serializer時,如果要保存反序列化后的實例到數據庫,則必須要實現這兩方法之一,生成的實例則作為save()返回值返回。方法屬性validated_data表示校驗的傳入數據。

3. is_valid()

當反序列化時,在調用Serializer.save()之前必須要使用is_valid()方法進行校驗,如果校驗成功返回True,失敗則返回False,同時會將錯誤信息保存到serializer.errors屬性中。

4.data

serializer.data中保存了序列化后的數據。

5.errors

當serializer.is_valid()進行校驗后,如果校驗失敗,則將錯誤信息保存到serializer.errors屬性中。

6.Serializer中的Field

在定義Model時,我們通過models.<FieldName>獲取了各種不同的字段,作為數據庫中表的一個列。而在Serializer中,也需要通過`serializers.<FieldName>的形式獲取對應Model的字段,用來在JSON數據和Python數據類型之間進行轉換,此外還可以根據Field中傳入的屬性進行校驗、設置默認值。以下對常用Serializer的Field進行整理。

使用時,需要導入所在模塊:

from rest_framework import serializers

 

1.CharField

對應models.CharField,同時如果指定長度,還會負責校驗文本長度。

max_length:最大長度;
min_length:最小長度;
allow_blank=True:表示允許將空串做為有效值,默認False;

2.EmailField

對應models.EmailField,驗證是否是有效email地址。

3.IntegerField

對應models.IntegerField,代表整數類型

4.FloatField

對應models.FloatField,代表浮點數類型

5.DateTimeField

對應models.DateTimeField,代表時間和日期類型。

format='YYYY-MM-DD hh:mm':指定datetime輸出格式,默認為DATETIME_FORMAT值。
需要注意,如果在 ModelSerializer 和HyperlinkedModelSerializer中如果models.DateTimeField帶有auto_now=True或者auto_add_now=True,則對應的serializers.DateTimeField中將默認使用屬性read_only=True,如果不想使用此行為,需要顯示對該字段進行聲明:

class CommentSerializer(serializers.ModelSerializer):
    created = serializers.DateTimeField()

    class Meta:
        model = Comment

6.FileField

對應models.FileField,代表一個文件,負責文件校驗。

max_length:文件名最大長度;
allow_empty_file:是否允許為空文件;

7.ImageField

對應models.ImageField,代表一個圖片,負責校驗圖片格式是否正確。

max_length:圖片名最大長度;
allow_empty_file:是否允許為空文件;
如果要進行圖片處理,推薦安裝Pillow: pip install Pillow

8.HiddenField

這是serializers中特有的Field,它不根據用戶提交獲取值,而是從默認值或可調用的值中獲取其值。一種常見的使用場景就是在Model中存在user_id作為外鍵,在用戶提交時,不允許提交user_id,但user_id在定義Model時又是必須字段,這種情況下就可以使用HiddenField提供一個默認值:

class LeavingMessageSerializer(serializers.Serializer):


    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )

6.serializers.Field中的公共參數

所謂公共參數,是指對於所有的serializers.<FieldName>都可以接受的參數。以下是常見的一些公共參數。

1.read_only

read_only=True表示該字段為只讀字段,即對應字段只用於序列化時(輸出),而在反序列化時(創建對象)不使用該字段。默認值為False。

2.write_only

write_only=True表示該字段為只寫字段,和read_only相反,即對應字段只用於更新或創建新的Model時,而在序列化時不使用,即不會輸出給用戶。默認值為False。

3.required

required=False表示對應字段在反序列化時是非必需的。在正常情況下,如果反序列化時缺少字段,則會拋出異常。默認值為True。

4.default

給字段指定一個默認值。需要注意,如果字段設置了default,則隱式地表示該字段已包含required=False,如果同時指定default和required,則會拋出異常。

5.allow_null

allow_null=True表示在序列化時允許None作為有效值。需要注意,如果沒有顯式使用default參數,則當指定allow_null=True時,在序列化過程中將會默認default=None,但並不會在反序列化時也默認。

6.validators

一個應用於傳入字段的驗證函數列表,如果驗證失敗,會引發驗證錯誤,否則直接是返回,用於驗證字段,如:

username = serializers.CharField(max_length=16, required=True, label='用戶名',
                                     validators=[validators.UniqueValidator(queryset=User.objects.all(),message='用戶已經存在')]) 


7.error_message

驗證時錯誤碼和錯誤信息的一個dict,可以指定一些驗證字段時的錯誤信息,如:

mobile= serializers.CharField(max_length=4, required=True, write_only=True, min_length=4,
                                 label='電話', error_messages={
                                    'blank': '請輸入驗證碼',
                                    'required': '該字段必填項',
                                    'max_length': '驗證碼格式錯誤',
                                    'min_length': '驗證碼格式錯誤',
                                })

7.style

一個鍵值對,用於控制字段如何渲染,最常用於對密碼進行密文輸入,如:

 password = serializers.CharField(max_length=16, min_length=6, required=True, label='密碼',
                                     error_messages={
                                         'blank': '請輸入密碼',
                                         'required': '該字段必填',
                                         'max_length': '密碼長度不超過16',
                                         'min_length': '密碼長度不小於6',

                                     },
                                     style={'input_type': 'password'}, write_only=True) 

9.label

一個簡短的文本字串,用來描述該字段。

10.help_text

一個文本字串,可用作HTML表單字段或其他描述性元素中字段的描述。

11.allow_blank

allow_blank=True 可以為空    設置False則不能為空

12.source

source='user.email'(user表的email字段的值給這值)  設置字段值  類似default   通常這個值有外鍵關聯屬性可以用source設置

13.validators

驗證該字段跟  單獨的validate很像

UniqueValidator 單獨唯一

validators=[UniqueValidator(queryset=UserProfile.objects.all())

UniqueTogetherValidator: 多字段聯合唯一,這個時候就不能單獨作用於某個字段,我們在Meta中設置。

validators = [UniqueTogetherValidator(queryset=UserFav.objects.all(),fields=('user', 'course'),message='已經收藏')]

14.error_messages

錯誤消息提示

error_messages={
"min_value": "商品數量不能小於一",
"required": "請選擇購買數量"
})

7.ModelSerializers

ModelSerializers繼承於Serializer,相比其父類,ModelSerializer自動實現了以下三個步驟:

  • 1.根據指定的Model自動檢測並生成序列化的字段,不需要提前定義;
  • 2.自動為序列化生成校驗器;
  • 3.自動實現了create()方法和update()方法。

使用ModelSerializer方式如下:

class StudentSerializer(serializers.ModelSerializer):
    class Meta:
        # 指定一個Model,自動檢測序列化的字段
        model = StudentSerializer
        fields = ('id', 'name', 'age', 'birthday')

相比於Serializer,可以說是簡單了不少,當然,有時根據項目要求,可能也會在ModelSerializer中顯示聲明字段,這些在后面總結。

model

該屬性指定一個Model類,ModelSerializer會根據提供的Model類自動檢測出需要序列化的字段。默認情況下,所有Model類中的字段將會映射到ModelSerializer類中相應的字段。

fields

如果不希望對Model中所有的字符進行序列化,可以在fields屬性中顯示指定要進行序列化的字段。

 


免責聲明!

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



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