Linux中國

如何在 Python Web 框架 Django 中使用序列化器

序列化是將數據轉換為可以存儲或傳輸的格式,然後對其進行重新構建的過程。在開發應用程序或將數據存儲在資料庫、內存或將其轉換為文件時,一直會用到它。

我最近幫助 Labcodes 的兩名初級開發人員理解序列化器,我想也可以與諸位讀者分享一下我的方法。

假設你正在編寫一個電子商務網站,你有一個訂單,該訂單記錄了某人在某個日期以某種價格購買了一個產品:

class Order:
    def __init__(self, product, customer, price, date):
        self.product = product
        self.customer = customer
        self.price = price
        self.date = date

現在,假設你想從一個鍵值資料庫中存儲和檢索訂單數據。幸運的是,它的介面可以接受和返回字典,因此你需要將對象轉換成字典:

def serialize_order(order):
    return {
        'product': order.product,
        'customer': order.customer,
        'price': order.price,
        'date': order.date
    }

如果你想從資料庫中獲取一些數據,你可以獲取字典數據並將其轉換為訂單對象(Order):

def deserialize_order(order_data):
    return Order(
        product=order_data['product'],
        customer=order_data['customer'],
        price=order_data['price'],
        date=order_data['date'],
    )

這對於簡單的數據非常直接了當,但是當你需要處理一些由複雜屬性構成的複雜對象時,這種方法就無法很好地擴展。你還需要處理不同類型欄位的驗證,這需要手工完成大量工作。

此時框架的序列化可以很方便的派上用場。它們使你可以創建帶有少量模板的序列化器,這將適用於複雜的情況。

Django 提供了一個序列化模塊,允許你將模型「轉換」為其它格式:

from django.core import serializers

serializers.serialize('json', Order.objects.all())

它涵蓋了 Web 應用程序最常用的種類,例如 JSON、YAML 和 XML。但是你也可以使用第三方序列化器或創建自己的序列化器。你只需要在 settings.py 文件中註冊它:

# settings.py
SERIALIZATION_MODULES = {
    'my_format': appname.serializers.MyFormatSerializer,
}

要創建自己的 MyFormatSerializer,你需要實現 .serialize() 方法並接受一個查詢集和其它選項作為參數:

class MyFormatSerializer:
    def serialize(self, queryset, **options):
        # serious serialization happening

現在,你可以將查詢集序列化為新格式:

from django.core import serializers

serializers.serialize('my_format', Order.objects.all())

你可以使用選項參數來定義序列化程序的行為。例如,如果要定義在處理 ForeignKeys 時要使用嵌套序列化,或者只希望數據返回其主鍵,你可以傳遞一個 flat=True 參數作為選項,並在方法中處理:

class MyFormatSerializer:
    def serializer(self, queryset, **options):
        if options.get('flat', False):
            # don't recursively serialize relationships
        # recursively serialize relationships

使用 Django 序列化的一種方法是使用 loaddatadumpdata 管理命令。

DRF 序列化器

在 Django 社區中,Django REST 框架(DRF)提供了最著名的序列化器。儘管你可以使用 Django 的序列化器來構建將在 API 中響應的 JSON,但 REST 框架中的序列化器提供了更出色的功能,可以幫助你處理並輕鬆驗證複雜的數據。

在訂單的例子中,你可以像這樣創建一個序列化器:

from restframework import serializers

class OrderSerializer(serializers.Serializer):
    product = serializers.CharField(max_length=255)
    customer = serializers.CharField(max_lenght=255)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    date = serializers.DateField()

輕鬆序列化其數據:

order = Order('pen', 'renato', 10.50, date.today())
serializer = OrderSerializer(order)

serializer.data
# {'product': 'pen', 'customer': 'renato', 'price': '10.50', 'date': '2020-08-16'}

為了能夠從數據返回實例,你需要實現兩個方法:createupdate

from rest_framework import serializers

class OrderSerializer(serializers.Serializer):
    product = serializers.CharField(max_length=255)
    customer = serializers.CharField(max_length=255)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    date = serializers.DateField()

    def create(self, validated_data):
        # 執行訂單創建
        return order

    def update(self, instance, validated_data):
       # 執行實例更新
       return instance

之後,你可以通過調用 is_valid() 來驗證數據,並通過調用 save() 來創建或更新實例:

serializer = OrderSerializer(**data)
## 若要驗證數據,在調用 save 之前必須執行
serializer.is_valid()
serializer.save()

模型序列化器

序列化數據時,通常需要從資料庫(即你創建的模型)進行數據處理。ModelSerializerModelForm 一樣,提供了一個 API,用於從模型創建序列化器。假設你有一個訂單模型:

from django.db import models

class Order(models.Model):
    product = models.CharField(max_length=255)
    customer = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    date = models.DateField()    

你可以像這樣為它創建一個序列化器:

from rest_framework import serializers

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = '__all__'

Django 會自動在序列化器中包含所有模型欄位,並創建 createudpate 方法。

在基於類的視圖(CBV)中使用序列化器

像 Django CBV 中的 Forms 一樣,序列化器可以很好地與 DRF 集成。你可以設置 serializer_class 屬性,方便序列化器用於視圖:

from rest_framework import generics

class OrderListCreateAPIView(generics.ListCreateAPIView):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

你也可以定義 get_serializer_class() 方法:

from rest_framework import generics

class OrderListCreateAPIView(generics.ListCreateAPIView):
    queryset = Order.objects.all()

    def get_serializer_class(self):
        if is_free_order():
            return FreeOrderSerializer
        return OrderSerializer

在 CBV 中還有其它與序列化器交互的方法。例如,get_serializer() 返回一個已經實例化的序列化器,get_serializer_context() 返回創建實例時傳遞給序列化器的參數。對於創建或更新數據的視圖,有 createupdate,它們使用 is_valid 方法驗證數據,還有 perform_createperform_update 調用序列化器的 save 方法。

了解更多

要了解更多資源,參考我朋友 André Ericson 的經典 Django REST 框架網站。它是一個基於類的經典視圖的 REST 框架版本,可讓你深入查看組成 DRF 的類。當然,官方文檔也是一個很棒的資源。

via: https://opensource.com/article/20/11/django-rest-framework-serializers

作者:Renato Oliveira 選題:lujun9972 譯者:MjSeven 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國