Django DRF - 序列化程序有什么用?

Pyt*_*ast 7 python django django-rest-framework

我已经使用 Django 3 年多了,但从来没有觉得需要使用 DRF。不过,看到DRF越来越流行,我想试一试。

序列化是我觉得最困难的概念。考虑例如:- 我想保存用户详细信息。以下是用户相关的模型。

class Users(models.Model):
    GENDER_CHOICES = (
        ('M', 'MALE'),
        ('F', 'FEMALE'),
        ('O', 'OTHERS'),
    )
    first_name = models.CharField(max_length=255, blank=True, null=True)
    middle_name = models.CharField(max_length=255, blank=True, null=True)
    last_name = models.CharField(max_length=255, blank=True, null=True)
    gender = models.CharField(choices=GENDER_CHOICES, max_length=1, blank=True,
                              null=True)


class UserAddress(models.Model):
    ADDRESS_TYPE_CHOICES = (
        ('P', 'Permanent'),
        ('Cu', 'Current'),
        ('Co', 'Correspondence')
    )
    line1 = models.CharField(max_length=255)
    line2 = models.CharField(max_length=255, blank=True, null=True)
    pincode = models.IntegerField()
    address_type = models.CharField(choices=ADDRESS_TYPE_CHOICES,
                                    max_length=255)
    user_id = models.ForeignKey(Users, related_name='uaddress')


class UserPhone(models.Model):
    phone = models.CharField(max_length=10)
    user_id = models.ForeignKey(Users, related_name='uphone')


class UserPastProfession(models.Model):
    profession = models.CharField(max_length=10)  # BusinessMan, software Engineer, Artist etc.
    user_id = models.ForeignKey(Users, related_name='uprofession')
Run Code Online (Sandbox Code Playgroud)

我将所有用户详细信息捆绑在一个 POST 端点中。

{
    'first_name': 'first_name',
    'middle_name': 'middle_name',
    'last_name': 'last_name',
    'gender': 'gender',
    'address': [{
        'line1': 'line1',
        'line2': 'line2',
        'address_type': 'address_type',
    }],
    'phone': ['phone1', 'phone2'],
    'profession': ['BusinessMan', 'Software Engineer', 'Artist']
}
Run Code Online (Sandbox Code Playgroud)

如果不使用 DRF,我会先创建一个Users对象,然后将它与UserAddress,UserPhoneUserPastProfessionobject链接起来。

如何使用 DRF 完成相同的工作?我的意思是validating, serializing, 然后保存细节。serializers.py 文件会是什么样子?

Sye*_*zan 12

如果你想让你的生活更轻松,你肯定会使用它。

序列化程序允许将查询集和模型实例等复杂数据转换为原生 Python 数据类型,然后可以轻松地将其呈现为 JSON、XML 或其他内容类型。序列化程序还提供反序列化,允许在首先验证传入数据后将解析的数据转换回复杂类型。

这为您提供了一种控制响应输出的通用方法,以及一个 ModelSerializer 类,该类为创建处理模型实例和查询集的序列化程序提供了有用的快捷方式。

它们使您免于编写大量自定义代码。让我们看一些例子。

假设我们有一个应用程序来跟踪用户必须在某个日期之前完成的任务列表。Task 模型可能如下所示:

class Task(models.Model):
    title = models.CharField(max_length=255)
    due_date = models.DateField() 
    completed = models.BooleanField(default=False)
Run Code Online (Sandbox Code Playgroud)

当用户请求这些任务时,我们的应用程序以 JSON 序列化字符串的形式返回响应。当我们尝试使用内置的 json 库序列化我们的 Django 对象时会发生什么?

import json
task = Task.objects.first()
json.dumps(task)
Run Code Online (Sandbox Code Playgroud)

我们得到一个类型错误。任务不是 JSON 可序列化的。为了绕过这个,我们必须显式地创建一个字典,其中包含 Task 中的每个属性。

json.dumps({
    'title': task.title,
    'due_date': task.due_date.strftime('%Y-%m-%d'),
    'completed': task.completed
}) 
Run Code Online (Sandbox Code Playgroud)

从 JSON 字符串或请求数据序列化 Python 对象同样痛苦。

from datetime import datetime 
title = request.data.get('title')
due_date = datetime.strptime(request.data.get('due_date'), '%Y-%m-%d').date()
completed = request.data.get('completed')
task = Task.objects.create(title=title, due_date=due_date, completed=completed) 
Run Code Online (Sandbox Code Playgroud)

现在,想象一下,如果您有多个 API 需要序列化(或反序列化)JSON 数据,则必须在多个视图中执行这些步骤。此外,如果您的 Django 模型发生变化,您必须跟踪并编辑所有自定义序列化代码。

创建和使用序列化程序很容易:

from rest_framework import serializers 
class TaskSerializer(serializers.ModelSerializer):
    def create(self, validated_data):
        return Task.objects.create(**validated_data)

    class Meta:
        model = Task
        fields = ('title', 'due_date', 'completed')

# Serialize Python object to JSON string. 
task_data = TaskSerializer(task).data 

# Create Python object from JSON string.
task_data = TaskSerializer(request.data)
task = task_data.create() 
Run Code Online (Sandbox Code Playgroud)

如果你更新 Django 模型,你只需要在一处更新序列化器,所有依赖它的代码都可以工作。您还可以获得许多其他好处,包括(如您所提到的)数据验证。

希望有帮助!


Ali*_*tov 3

如果我没猜错的话,我的答案是:

没有必要为模型编写一个序列化器,即使是方法类型(POST、GET 等)。您几乎可以根据需要为模型创建序列化器并设置要操作的字段。您还可以将这些不同的序列化器设置为每个方法的 APIView 类的 serializer_class 属性。

我强烈建议你花一些时间看看Django Rest Framework 教程