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

开发 后端
序列化用于将数据转换为方便存储或传输的格式,然后将其重新构建以供使用。DRF 是最具有知名的序列化器。

[[356442]]

序列化用于将数据转换为方便存储或传输的格式,然后将其重新构建以供使用。DRF 是最具有知名的序列化器。

序列化是将数据转换为可以存储或传输的格式,然后对其进行重新构建的过程。在开发应用程序或将数据存储在数据库、内存或将其转换为文件时,一直会用到它。

我最近帮助 Labcodes 的两名初级开发人员理解序列化器,我想也可以与诸位读者分享一下我的方法。

假设你正在编写一个电子商务网站,你有一个订单,该订单记录了某人在某个日期以某种价格购买了一个产品:

  1. class Order:
  2.     def __init__(self, product, customer, price, date):
  3.         self.product = product
  4.         self.customer = customer
  5.         self.price = price
  6.         self.date = date

现在,假设你想从一个键值数据库中存储和检索订单数据。幸运的是,它的接口可以接受和返回字典,因此你需要将对象转换成字典:

  1. def serialize_order(order):
  2.     return {
  3.         'product': order.product,
  4.         'customer': order.customer,
  5.         'price': order.price,
  6.         'date': order.date
  7.     }

如果你想从数据库中获取一些数据,你可以获取字典数据并将其转换为订单对象(Order):

  1. def deserialize_order(order_data):
  2.     return Order(
  3.         product=order_data['product'],
  4.         customer=order_data['customer'],
  5.         price=order_data['price'],
  6.         date=order_data['date'],
  7.     )

这对于简单的数据非常直接了当,但是当你需要处理一些由复杂属性构成的复杂对象时,这种方法就无法很好地扩展。你还需要处理不同类型字段的验证,这需要手工完成大量工作。

此时框架的序列化可以很方便的派上用场。它们使你可以创建带有少量模板的序列化器,这将适用于复杂的情况。

Django 提供了一个序列化模块,允许你将模型“转换”为其它格式:

  1. from django.core import serializers
  2.  
  3. serializers.serialize('json', Order.objects.all())

它涵盖了 Web 应用程序最常用的种类,例如 JSON、YAML 和 XML。但是你也可以使用第三方序列化器或创建自己的序列化器。你只需要在 settings.py 文件中注册它:

  1. # settings.py
  2. SERIALIZATION_MODULES = {
  3.     'my_format': appname.serializers.MyFormatSerializer,
  4. }

要创建自己的 MyFormatSerializer,你需要实现 .serialize() 方法并接受一个查询集和其它选项作为参数:

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

现在,你可以将查询集序列化为新格式:

  1. from django.core import serializers
  2.  
  3. serializers.serialize('my_format', Order.objects.all())

你可以使用选项参数来定义序列化程序的行为。例如,如果要定义在处理 ForeignKeys 时要使用嵌套序列化,或者只希望数据返回其主键,你可以传递一个 flat=True 参数作为选项,并在方法中处理:

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

使用 Django 序列化的一种方法是使用 loaddata 和 dumpdata 管理命令。

DRF 序列化器

在 Django 社区中,Django REST 框架(DRF)提供了最著名的序列化器。尽管你可以使用 Django 的序列化器来构建将在 API 中响应的 JSON,但 REST 框架中的序列化器提供了更出色的功能,可以帮助你处理并轻松验证复杂的数据。

在订单的例子中,你可以像这样创建一个序列化器:

  1. from restframework import serializers
  2.  
  3. class OrderSerializer(serializers.Serializer):
  4.     product = serializers.CharField(max_length=255)
  5.     customer = serializers.CharField(max_lenght=255)
  6.     price = serializers.DecimalField(max_digits=5, decimal_places=2)
  7.     date = serializers.DateField()

轻松序列化其数据:

  1. order = Order('pen', 'renato', 10.50, date.today())
  2. serializer = OrderSerializer(order)
  3.  
  4. serializer.data
  5. # {'product': 'pen', 'customer': 'renato', 'price': '10.50', 'date': '2020-08-16'}

为了能够从数据返回实例,你需要实现两个方法:create 和 update

  1. from rest_framework import serializers
  2.  
  3. class OrderSerializer(serializers.Serializer):
  4.     product = serializers.CharField(max_length=255)
  5.     customer = serializers.CharField(max_length=255)
  6.     price = serializers.DecimalField(max_digits=5, decimal_places=2)
  7.     date = serializers.DateField()
  8.  
  9.     def create(self, validated_data):
  10.         # 执行订单创建
  11.         return order
  12.  
  13.     def update(self, instance, validated_data):
  14.        # 执行实例更新
  15.        return instance

之后,你可以通过调用 is_valid() 来验证数据,并通过调用 save() 来创建或更新实例:

  1. serializer = OrderSerializer(**data)
  2. ## 若要验证数据,在调用 save 之前必须执行
  3. serializer.is_valid()
  4. serializer.save()

模型序列化器

序列化数据时,通常需要从数据库(即你创建的模型)进行数据处理。ModelSerializer 与 ModelForm 一样,提供了一个 API,用于从模型创建序列化器。假设你有一个订单模型:

  1. from django.db import models
  2.  
  3. class Order(models.Model):
  4.     product = models.CharField(max_length=255)
  5.     customer = models.CharField(max_length=255)
  6.     price = models.DecimalField(max_digits=5, decimal_places=2)
  7.     date = models.DateField()    

你可以像这样为它创建一个序列化器:

  1. from rest_framework import serializers
  2.  
  3. class OrderSerializer(serializers.ModelSerializer):
  4.     class Meta:
  5.         model = Order
  6.         fields = '__all__'

Django 会自动在序列化器中包含所有模型字段,并创建 create 和 udpate 方法。

在基于类的视图(CBV)中使用序列化器

像 Django CBV 中的 Forms 一样,序列化器可以很好地与 DRF 集成。你可以设置 serializer_class 属性,方便序列化器用于视图:

  1. from rest_framework import generics
  2.  
  3. class OrderListCreateAPIView(generics.ListCreateAPIView):
  4.     queryset = Order.objects.all()
  5.     serializer_class = OrderSerializer

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

  1. from rest_framework import generics
  2.  
  3. class OrderListCreateAPIView(generics.ListCreateAPIView):
  4.     queryset = Order.objects.all()
  5.    
  6.     def get_serializer_class(self):
  7.         if is_free_order():
  8.             return FreeOrderSerializer
  9.         return OrderSerializer

在 CBV 中还有其它与序列化器交互的方法。例如,get_serializer() 返回一个已经实例化的序列化器,get_serializer_context() 返回创建实例时传递给序列化器的参数。对于创建或更新数据的视图,有 create 和 update,它们使用 is_valid 方法验证数据,还有 perform_create 和 perform_update 调用序列化器的 save 方法。

了解更多

要了解更多资源,参考我朋友 André Ericson 的经典 Django REST 框架网站。它是一个基于类的经典视图的 REST 框架版本,可让你深入查看组成 DRF 的类。当然,官方文档也是一个很棒的资源。 

责任编辑:庞桂玉 来源: Linux中国
相关推荐

2021-06-09 09:36:18

DjangoElasticSearLinux

2023-12-13 13:49:52

Python序列化模块

2022-05-10 09:12:16

TypeScript装饰器

2022-08-06 08:41:18

序列化反序列化Hessian

2022-06-23 08:00:53

PythonDateTime模块

2022-03-09 07:10:50

Quarkus框架项目

2009-08-24 17:14:08

C#序列化

2011-06-01 15:05:02

序列化反序列化

2011-06-01 15:18:43

Serializabl

2020-09-09 07:00:00

TensorFlow神经网络人工智能

2010-03-10 14:03:41

python处理文本

2009-03-10 13:38:01

Java序列化字节流

2010-01-08 13:25:07

ibmdwXML

2023-08-24 10:24:54

GitLabPodman

2018-03-19 10:20:23

Java序列化反序列化

2009-08-06 11:16:25

C#序列化和反序列化

2011-05-18 15:20:13

XML

2022-09-21 07:57:56

面部识别身份认证。Web

2023-11-20 08:44:18

数据序列化反序列化

2009-08-25 14:24:36

C#序列化和反序列化
点赞
收藏

51CTO技术栈公众号