【django】Django REST Framework 序列化与反序列化详解

目录

1、什么是序列化和反序列化?

[2、Django REST Framework中的序列化和反序列化](#2、Django REST Framework中的序列化和反序列化)

3、安装与配置(第10章是从零开始)

[3.1 安装](#3.1 安装)

[3.2 配置](#3.2 配置)

4、基本使用

[4.1 创建序列化器](#4.1 创建序列化器)

[4.2 使用序列化器(将数据序列化返回给前端)](#4.2 使用序列化器(将数据序列化返回给前端))

[4.3 配置url](#4.3 配置url)

[4.4 测试](#4.4 测试)

[4.5 反序列化(从前端获取数据反序列化)](#4.5 反序列化(从前端获取数据反序列化))

[4.5.1 url配置](#4.5.1 url配置)

[4.5.2 测试](#4.5.2 测试)

[4.6 数据验证(将4.1的序列化设置验证方式多样化)](#4.6 数据验证(将4.1的序列化设置验证方式多样化))

5、一对多模型序列化

[5.1 模型定义](#5.1 模型定义)

[5.2 序列化器定义](#5.2 序列化器定义)

[5.3 使用序列化器](#5.3 使用序列化器)

[5.4 url配置](#5.4 url配置)

[5.5 测试](#5.5 测试)

6、多对多关系

[6.1 模型定义](#6.1 模型定义)

[6.2 序列化器定义](#6.2 序列化器定义)

[6.3 使用序列化器](#6.3 使用序列化器)

[6.4 url配置](#6.4 url配置)

[6.5 测试](#6.5 测试)

7、自定义字段

[7.1 模型定义](#7.1 模型定义)

[7.2 序列化器定义](#7.2 序列化器定义)

[7.3 使用序列化器](#7.3 使用序列化器)

[7.4 配置url](#7.4 配置url)

[7.5 测试](#7.5 测试)

[7.6 使用depth优化序列化器](#7.6 使用depth优化序列化器)

8、来个多表级联

[8.1 模型定义](#8.1 模型定义)

[8.2 序列化器定义](#8.2 序列化器定义)

[8.3 使用序列化器](#8.3 使用序列化器)

[8.4 配置URL](#8.4 配置URL)

[8.5 测试](#8.5 测试)

9、总结

10、前期工作

[10.1 创建django项目](#10.1 创建django项目)

[10.2 安装库](#10.2 安装库)

[10.3 配置](#10.3 配置)

[10.3.1 创建mysql数据库drf](#10.3.1 创建mysql数据库drf)

[10.3.2 配置mysql数据](#10.3.2 配置mysql数据)

[10.3.3 settings配置](#10.3.3 settings配置)

[10.3.4 apps.py](#10.3.4 apps.py)

[10.3.5 DRFDemo的urls配置](#10.3.5 DRFDemo的urls配置)

[10.3.6 drf的urls配置](#10.3.6 drf的urls配置)

[10.3.7 新建库表之后操作(非必须)](#10.3.7 新建库表之后操作(非必须))

[10.4 同步数据库](#10.4 同步数据库)

[10.5 创建超级用户](#10.5 创建超级用户)

[10.6 启动服务](#10.6 启动服务)

[10.7 访问](#10.7 访问)

[10.7.1 后端管理页面](#10.7.1 后端管理页面)

[10.7.2 默认页面](#10.7.2 默认页面)


前言:Django REST Framework 序列化与反序列化详解,包含一对一,一对多,多对多的关系。

在当今的Web开发中,前后端分离已经成为一种趋势。在这种模式下,后端主要负责数据处理和业务逻辑,而前端则专注于用户界面和交互。为了有效地在前后端之间传输数据,通常使用JSON这种轻量级的数据交换格式。Django REST Framework(DRF)作为一个强大的Django扩展,提供了便捷的REST API开发框架,其中的序列化和反序列化功能正是实现这一传输的关键。

1、什么是序列化和反序列化?

  • 序列化:将Python对象转换为JSON或其他文本格式,以便通过HTTP进行传输。
  • 反序列化:将JSON数据转换回Python对象,以便在后端进行处理。

2、Django REST Framework中的序列化和反序列化

DRF通过序列化器(Serializer)来实现这一功能。序列化器不仅负责数据的转换,还提供了数据验证和渲染的功能。

3、安装与配置(第10章是从零开始)

3.1 安装

首先,你需要安装Django REST Framework:

pip install djangorestframework

3.2 配置

然后,在你的settings.py文件中,将rest_framework添加到INSTALLED_APPS中:

INSTALLED_APPS = [  
    ...  
    'rest_framework',  
    ...  
]

4、基本使用

4.1 创建序列化器

序列化器通常定义在应用程序下的serializers.py文件中。你可以通过继承serializers.Serializerserializers.ModelSerializer来创建自定义序列化器。

例如,假设你有一个Book模型:

from django.db import models  
  
class Book(models.Model):  
    title = models.CharField(max_length=100)  
    author = models.CharField(max_length=50)  
    publication_date = models.DateField()
    class Meta:
        managed = True
        db_table = 'book'
        verbose_name_plural = '书籍表'

你可以创建一个对应的序列化器:

from rest_framework import serializers  
from .models import Book  
  
class BookSerializer(serializers.ModelSerializer):  
    class Meta:  
        model = Book  
        fields = '__all__'  # 或者指定需要序列化的字段,如 ['title', 'author', 'publication_date']

4.2 使用序列化器(将数据序列化返回给前端)

在视图中,你可以通过实例化序列化器对象,并将要序列化的数据传递给instance参数(对于单个对象)或many=True(对于多个对象)来进行序列化。

from rest_framework.views import APIView  
from rest_framework.response import Response  
from .models import Book  
from .serializers import BookSerializer  
  
class BookListView(APIView):  
    def get(self, request, *args, **kwargs):  
        books = Book.objects.all()  
        serializer = BookSerializer(books, many=True)  
        return Response(serializer.data)

4.3 配置url

urlpatterns = [
    # path('', views.index, name='index'),  # 定义一个根路由,指向 index 视图
    # 你可以在这里添加更多的路由
    path('books/', BookListView.as_view(), name='book-list'),
]

4.4 测试

返回数据

[
    {
        "id": 1,
        "title": "西游记",
        "author": "吴承恩",
        "publication_date": "2024-10-29"
    },
    {
        "id": 2,
        "title": "红楼梦",
        "author": "曹雪芹",
        "publication_date": "2024-10-30"
    },
    {
        "id": 3,
        "title": "水浒传",
        "author": "施耐庵",
        "publication_date": "2024-10-07"
    },
    {
        "id": 4,
        "title": "三国演义",
        "author": "罗贯中",
        "publication_date": "2024-10-11"
    }
]

4.5 反序列化(从前端获取数据反序列化)

对于反序列化,你需要将前端传来的JSON数据传递给data参数,并调用is_valid()方法进行验证。如果验证通过,你可以调用save()方法将数据存储到数据库中。

class BookCreateView(APIView):  
    def post(self, request, *args, **kwargs):  
        serializer = BookSerializer(data=request.data)  
        if serializer.is_valid():  
            serializer.save()  
            return Response(serializer.data, status=201)  
        return Response(serializer.errors, status=400)

4.5.1 url配置

urlpatterns = [  
    path('books/', BookListView.as_view(), name='book-list'),  
    path('books/create/', BookCreateView.as_view(), name='book-create'),  # 新增的路径  
]

4.5.2 测试

现在你可以使用工具(如 Postman)来测试你的创建接口。发送一个 POST 请求到 http://localhost:8000/books/create/,并在请求体中提供书籍的数据(JSON 格式):

{  
    "title": "Django REST Framework 序列化与反序列化详解",  
    "author": "春天的菠菜",  
    "publication_date": "2024-11-01"  
}

4.6 数据验证(将4.1的序列化设置验证方式多样化)

在序列化器中,你可以通过指定字段的验证参数(如max_lengthmin_lengthrequired等)来进行数据验证。此外,你还可以定义validate_<field_name>方法来对单个字段进行自定义验证,或者定义validate方法来对多个字段进行联合验证。

class BookSerializer(serializers.ModelSerializer):  
    title = serializers.CharField(max_length=100, min_length=5)  
  
    def validate_title(self, value):  
        if 'badword' in value.lower():  
            raise serializers.ValidationError('Title contains bad words.')  
        return value  
  
    def validate(self, attrs):  
        if attrs['author'] == 'Unknown':  
            raise serializers.ValidationError({'author': 'Author cannot be Unknown.'})  
        return attrs  
  
    class Meta:  
        model = Book  
        fields = '__all__'

5、一对多模型序列化

5.1 模型定义

class Department(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name
    class Meta:
        managed = True
        db_table = 'department'

class Employee(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    department = models.ForeignKey(Department, on_delete=models.CASCADE)
    hire_date = models.DateField()

    def __str__(self):
        return f"{self.first_name} {self.last_name}"
    class Meta:
        managed = True
        db_table = 'employee'

5.2 序列化器定义

在序列化器中,你可以使用serializers.PrimaryKeyRelatedFieldserializers.StringRelatedField来引用关联对象的主键或字符串表示,或者使用嵌套的序列化器来表示关联对象的完整数据。

from rest_framework import serializers
from .models import Department, Employee

class DepartmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Department
        fields = ['id', 'name', 'description']

class EmployeeSerializer(serializers.ModelSerializer):
    department = DepartmentSerializer()  # 使用嵌套的序列化器

    class Meta:
        model = Employee
        fields = ['id', 'first_name', 'last_name', 'department', 'hire_date']

在这个例子中,EmployeeSerializer中的department字段使用了DepartmentSerializer作为嵌套序列化器,这样当序列化Employee对象时,department字段将包含完整的Department对象数据。

5.3 使用序列化器

# newapp/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Employee
from .serializers import EmployeeSerializer

class EmployeeListView(APIView):
    def get(self, request, *args, **kwargs):
        employees = Employee.objects.all().select_related('department')  # 使用select_related优化查询
        serializer = EmployeeSerializer(employees, many=True)
        return Response(serializer.data)

5.4 url配置

# newapp/urls.py
from django.urls import path
from .views import EmployeeListView

urlpatterns = [
    path('employees/', EmployeeListView.as_view(), name='employee-list'),
]

5.5 测试

返回的数据展示

[
    {
        "id": 1,
        "first_name": "Michelle",
        "last_name": "Jackson",
        "department": {
            "id": 1,
            "name": "公关部",
            "description": "外部公关"
        },
        "hire_date": "2024-10-01"
    },
    {
        "id": 2,
        "first_name": "John",
        "last_name": "Smith",
        "department": {
            "id": 2,
            "name": "市场部",
            "description": "开拓市场"
        },
        "hire_date": "2024-10-30"
    },
    {
        "id": 3,
        "first_name": "Mary",
        "last_name": "Johnson",
        "department": {
            "id": 1,
            "name": "公关部",
            "description": "外部公关"
        },
        "hire_date": "2024-10-30"
    }
]

6、多对多关系

现在,假设我们有一个 Role 模型和一个 Permission 模型,其中 Role 模型有一个 permissions 字段,指向 Permission 模型,表示每个角色拥有的权限。这就是一个典型的多对多关系,因为一个角色可以拥有多个权限,同时一个权限也可以被多个角色拥有。

6.1 模型定义

# newapp/models.py
from django.db import models

class Permission(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name

class Role(models.Model):
    name = models.CharField(max_length=100)
    permissions = models.ManyToManyField(Permission)

    def __str__(self):
        return self.name

库里实际生成了三张表

6.2 序列化器定义

对于多对多关系,你可以使用serializers.PrimaryKeyRelatedFieldmany=True参数来引用关联对象的主键列表,或者使用嵌套的序列化器列表来表示关联对象的完整数据。

# newapp/serializers.py
from rest_framework import serializers
from .models import Permission, Role

class PermissionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Permission
        fields = ['id', 'name', 'description']

class RoleSerializer(serializers.ModelSerializer):
    permissions = PermissionSerializer(many=True)  # 使用嵌套的序列化器列表

    class Meta:
        model = Role
        fields = ['id', 'name', 'permissions']

在这个例子中,RoleSerializer 中的 permissions 字段使用了 PermissionSerializer 作为嵌套序列化器,并且设置了 many=True,这样当序列化 Role 对象时,permissions 字段将包含 Permission 对象数据的列表。

6.3 使用序列化器

无论是对于一对多关系还是多对多关系,使用序列化器的方式都是相同的。你可以在视图中实例化序列化器对象,并将要序列化的数据传递给instance参数(对于单个对象)或many=True(对于多个对象),然后进行序列化。

# newapp/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Role
from .serializers import RoleSerializer

class RoleListView(APIView):
    def get(self, request, *args, **kwargs):
        roles = Role.objects.all().prefetch_related('permissions')  # 使用prefetch_related优化查询
        serializer = RoleSerializer(roles, many=True)
        return Response(serializer.data)

注意,在上面的例子中,我们使用了prefetch_related来优化查询性能,这样可以减少数据库查询的次数。

6.4 url配置

# newapp/urls.py
from django.urls import path
from .views import RoleListView

urlpatterns = [
    path('roles/', RoleListView.as_view(), name='role-list'),
]

6.5 测试

返回数据

[
    {
        "id": 1,
        "name": "经理",
        "permissions": [
            {
                "id": 1,
                "name": "人员跟踪",
                "description": "人员动向"
            },
            {
                "id": 2,
                "name": "职能级别",
                "description": "客户职能级别"
            },
            {
                "id": 3,
                "name": "固定资产",
                "description": "固定资产"
            }
        ]
    },
    {
        "id": 2,
        "name": "部长",
        "permissions": [
            {
                "id": 2,
                "name": "职能级别",
                "description": "客户职能级别"
            },
            {
                "id": 3,
                "name": "固定资产",
                "description": "固定资产"
            }
        ]
    }
]

7、自定义字段

包含choices类型、外键、ManyToMany

7.1 模型定义

# newapp/models.py
from django.db import models

class Team(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name

class Task(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name

class Member(models.Model):
    STATUS_CHOICES = [
        (0, '无效的'),
        (1, '活跃的'),
        (2, '待定的')
    ]

    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    status = models.IntegerField(choices=STATUS_CHOICES, default=1)
    team = models.ForeignKey(Team, on_delete=models.CASCADE)
    tasks = models.ManyToManyField(Task, blank=True)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

7.2 序列化器定义

定义 TeamSerializer、TaskSerializer 和 MemberSerializer,并在 MemberSerializer 中嵌套 TeamSerializer 和 TaskSerializer 列表,并添加自定义字段 status_name 来显示 status 的可读名称。

# newapp/serializers.py
from rest_framework import serializers
from .models import Team, Task, Member

class TeamSerializer(serializers.ModelSerializer):
    class Meta:
        model = Team
        fields = ['id', 'name', 'description']

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = ['id', 'name', 'description']

class MemberSerializer(serializers.ModelSerializer):
    team = TeamSerializer(read_only=True)
    tasks = TaskSerializer(many=True, read_only=True)
    status_name = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = Member
        fields = ['id', 'first_name', 'last_name', 'status', 'status_name', 'team', 'tasks']

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        
        # 添加自定义字段:任务数量
        representation['task_count'] = instance.tasks.count()
        
        # 你可以在这里添加更多的自定义字段或修改现有的字段
        # 例如,你可能想根据某些条件改变状态名称的颜色
        # representation['status_color'] = 'green' if instance.status == 1 else 'red'
        
        return representation

to_representation 方法,它会在序列化每个 Member实例时被调用。这个方法允许我们添加自定义字段到序列化的数据中。在这个例子中,我们添加了一个 task_count 字段,它显示了每个成员的任务数量。

7.3 使用序列化器

# newapp/views.py
from rest_framework.views import APIView
from .models import Member
from .serializers import MemberSerializer
from rest_framework import status

class MemberListView(APIView):
    def get(self, request, *args, **kwargs):
        members = Member.objects.all().prefetch_related('tasks').select_related('team')  # 使用 prefetch_related 和 select_related 优化查询
        serializer = MemberSerializer(members, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

7.4 配置url

urlpatterns = [  
     path('members/', MemberListView.as_view(), name='member-list'),
]

7.5 测试

返回数据

[
    {
        "id": 1,
        "first_name": "Mary",
        "last_name": "Smith",
        "status": 1,
        "status_name": "活跃的",
        "team": {
            "id": 2,
            "name": "傲世天骄",
            "description": "绝色天骄团队"
        },
        "tasks": [],
        "task_count": 0
    },
    {
        "id": 2,
        "first_name": "Michelle",
        "last_name": "Jackson",
        "status": 2,
        "status_name": "待定的",
        "team": {
            "id": 1,
            "name": "海豹突击队",
            "description": "精英男士"
        },
        "tasks": [
            {
                "id": 1,
                "name": "拜访傲视群雄世家",
                "description": "拜访傲视群雄世家,获取订单需求"
            },
            {
                "id": 2,
                "name": "拜访独孤求败世家",
                "description": "拜访独孤求败世家,获取人脉资源"
            },
            {
                "id": 3,
                "name": "拜访东方不败世家",
                "description": "拜访东方不败世家,提供美颜代言"
            }
        ],
        "task_count": 3
    },
    {
        "id": 3,
        "first_name": "John",
        "last_name": "Jackson",
        "status": 1,
        "status_name": "活跃的",
        "team": {
            "id": 2,
            "name": "傲世天骄",
            "description": "绝色天骄团队"
        },
        "tasks": [
            {
                "id": 1,
                "name": "拜访傲视群雄世家",
                "description": "拜访傲视群雄世家,获取订单需求"
            },
            {
                "id": 2,
                "name": "拜访独孤求败世家",
                "description": "拜访独孤求败世家,获取人脉资源"
            },
            {
                "id": 3,
                "name": "拜访东方不败世家",
                "description": "拜访东方不败世家,提供美颜代言"
            }
        ],
        "task_count": 3
    }
]

7.6 使用depth优化序列化器

class MemberSerializer(serializers.ModelSerializer):
    status_name = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = Member
        fields = ['id', 'first_name', 'last_name', 'status', 'status_name', 'team', 'tasks']
        depth = 1  # 设置 depth=1 来自动序列化关联对象

    def to_representation(self, instance):
        representation = super().to_representation(instance)

        # 添加自定义字段:任务数量
        representation['task_count'] = instance.tasks.count()

        # 你可以在这里添加更多的自定义字段或修改现有的字段
        # 例如,你可能想根据某些条件改变状态名称的颜色
        # representation['status_color'] = 'green' if instance.status == 1 else 'red'

        return representation

这样做的好处是代码变得更简洁了,不需要单独定义 TeamSerializer 和 TaskSerializer,也不需要显式地设置它们为只读或使用 many=True。但是,请注意以下几点:

  • 性能问题:使用 depth 可能会导致额外的数据库查询,特别是在处理多对多关系时。
  • 灵活性减少:你将无法轻松地添加自定义字段到嵌套的序列化器中。
  • 控制力减弱:你将无法控制嵌套序列化器的具体行为,例如选择要包含的字段

8、来个多表级联

设计一个多表查询系统,包括省、市、县/区、街道、居委会以及人员信息。我们将使用 Django 模型来定义这些表,并创建相应的序列化器和视图。最后,我们会配置 URL 并提供测试逻辑。

8.1 模型定义

我们首先定义六张表:Province(省)、City(市)、County(县/区)、Street(街道)、Community(居委会)和 Person(人员)

# newapp/models.py
from django.db import models

class Province(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name

class City(models.Model):
    name = models.CharField(max_length=100)
    province = models.ForeignKey(Province, on_delete=models.CASCADE)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name

class County(models.Model):
    name = models.CharField(max_length=100)
    city = models.ForeignKey(City, on_delete=models.CASCADE)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name

class Street(models.Model):
    name = models.CharField(max_length=100)
    county = models.ForeignKey(County, on_delete=models.CASCADE)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name

class Community(models.Model):
    name = models.CharField(max_length=100)
    street = models.ForeignKey(Street, on_delete=models.CASCADE)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name

class Person(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    community = models.ForeignKey(Community, on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

8.2 序列化器定义

我们将使用 depth 参数来自动序列化关联对象。我们只需要为 Person 定义一个序列化器,并设置 depth 参数

# newapp/serializers.py
from rest_framework import serializers
from .models import Person

class PersonSerializer(serializers.ModelSerializer):
    full_address = serializers.SerializerMethodField()

    class Meta:
        model = Person
        fields = ['id', 'first_name', 'last_name', 'community', 'full_address']
        depth = 5  # 设置 depth 为 5 来自动序列化所有关联对象

    def get_full_address(self, obj):
        parts = [
            obj.community.street.county.city.province.name,
            obj.community.street.county.city.name,
            obj.community.street.county.name,
            obj.community.street.name,
            obj.community.name
        ]
        return ', '.join(parts)

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        # 可以在这里添加其他自定义字段
        return representation

8.3 使用序列化器

我们定义一个 APIView 来处理获取所有人员的请求,并使用 select_related 和 prefetch_related 来优化查询

# newapp/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Person
from .serializers import PersonSerializer

class PersonListView(APIView):
    def get(self, request, *args, **kwargs):
        persons = Person.objects.all().select_related(
            'community__street__county__city__province'
        )
        serializer = PersonSerializer(persons, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

8.4 配置URL

# newapp/urls.py
from django.urls import path
from .views import PersonListView

urlpatterns = [
    path('persons/', PersonListView.as_view(), name='person-list'),
]

8.5 测试

返回数据

[
    {
        "id": 1,
        "first_name": "Michelle",
        "last_name": "Johnson",
        "community": {
            "id": 1,
            "name": "青年路社区居民委员会",
            "description": "",
            "street": {
                "id": 1,
                "name": "湖滨街道",
                "description": "",
                "county": {
                    "id": 1,
                    "name": "上城区",
                    "description": "",
                    "city": {
                        "id": 2,
                        "name": "杭州市",
                        "description": "",
                        "province": {
                            "id": 2,
                            "name": "浙江省",
                            "description": ""
                        }
                    }
                }
            }
        },
        "full_address": "浙江省, 杭州市, 上城区, 湖滨街道, 青年路社区居民委员会"
    },
    {
        "id": 2,
        "first_name": "Mary",
        "last_name": "Smith",
        "community": {
            "id": 1,
            "name": "青年路社区居民委员会",
            "description": "",
            "street": {
                "id": 1,
                "name": "湖滨街道",
                "description": "",
                "county": {
                    "id": 1,
                    "name": "上城区",
                    "description": "",
                    "city": {
                        "id": 2,
                        "name": "杭州市",
                        "description": "",
                        "province": {
                            "id": 2,
                            "name": "浙江省",
                            "description": ""
                        }
                    }
                }
            }
        },
        "full_address": "浙江省, 杭州市, 上城区, 湖滨街道, 青年路社区居民委员会"
    },
    {
        "id": 3,
        "first_name": "John",
        "last_name": "Smith",
        "community": {
            "id": 2,
            "name": "百子亭社区",
            "description": "",
            "street": {
                "id": 2,
                "name": "玄武门街道",
                "description": "",
                "county": {
                    "id": 2,
                    "name": "玄武区",
                    "description": "",
                    "city": {
                        "id": 1,
                        "name": "南京市",
                        "description": "市区",
                        "province": {
                            "id": 1,
                            "name": "江苏省",
                            "description": ""
                        }
                    }
                }
            }
        },
        "full_address": "江苏省, 南京市, 玄武区, 玄武门街道, 百子亭社区"
    }
]

9、总结

Django REST Framework的序列化和反序列化功能为开发RESTful API提供了极大的便利。通过定义序列化器,你可以轻松地将Python对象转换为JSON格式,并从JSON数据恢复为Python对象。同时,序列化器还提供了强大的数据验证功能,确保数据的合法性和完整性。掌握这些技能,将帮助你更高效地开发前后端分离的Web应用。

扩展知识点: 在5与6章节 使用了这2个知识点,prefetch_related 适用于"一对多"的关系,即外键和多对多关系。如果你有"多对一"或"多对多"的关系,并且你想优化查询,可以使用 select_related

在使用 prefetch_relatedselect_related 时,你需要确保你的查询逻辑允许这种优化,并且你的数据库设计和索引也支持这种优化。此外,过度使用 prefetch_relatedselect_related 可能会导致内存使用增加,因为它们会一次性加载更多的数据到内存中。因此,在使用这些优化技术时,需要根据实际情况进行权衡。

10、前期工作

10.1 创建django项目

10.2 安装库

pip install pymysql

# rest_framework
pip install djangorestframework
 
# django后台页面美化  simpleui  非必须
pip install django-simpleui -i https://pypi.tuna.tsinghua.edu.cn/simple

10.3 配置

10.3.1 创建mysql数据库drf

10.3.2 配置mysql数据

DRFDemo下的__init__.py配置

import pymysql
pymysql.install_as_MySQLdb()

10.3.3 settings配置

INSTALLED_APPS = [
     'simpleui',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'drf.apps.DrfConfig',
    'rest_framework',
    'simpleui'
]


DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql',  # 数据库的类型
                'NAME': 'drf',  # 所使用的的数据库的名字
                'USER': 'root',  # 数据库服务器的用户
                'PASSWORD': 'dddd',  # 密码
                'HOST': 'IP',  # 主机
                'PORT': '3306',  # 端口
            }
}


#  国际化配置
LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_TZ = False

USE_I18N = True

10.3.4 apps.py

from django.apps import AppConfig


class DrfConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'drf'
    verbose_name = '首页欢迎你'

10.3.5 DRFDemo的urls配置

from django.contrib import admin
from django.urls import path, include


urlpatterns = [
    path('admin/', admin.site.urls),
    path('smart/', include('smart.urls')),

]

10.3.6 drf的urls配置

在drf下新建urls.py 后续的路由在这里配置

from django.urls import path
from . import views  # 假设你的视图函数定义在 views.py 中

urlpatterns = [
    # path('', views.index, name='index'),  # 定义一个根路由,指向 index 视图
    # 你可以在这里添加更多的路由
]

10.3.7 新建库表之后操作(非必须)

新库表这里配置就可在后台页面操作

from .models import Book
from django.contrib import admin

# Register your models here.
admin.site.register(Book)

10.4 同步数据库

python manage.py makemigrations
python manage.py migrate

10.5 创建超级用户

# 输入命令
createsuperuser
 
 
# 创建用户root
root
 
# 邮箱
market@163.com
 
#密码
123456
 
# 再次输入密码
123456
 
# 提示密码不安全,输入Y
y

10.6 启动服务

python manage.py runserver

10.7 访问

10.7.1 后端管理页面

http://127.0.0.1:8000/admin/

10.7.2 默认页面

http://127.0.0.1:8000/
相关推荐
呆呆小雅5 小时前
C# 可空类型
数据库·oracle·c#
Duck Bro5 小时前
MySQL:常用数据类型
java·数据库·c++·mysql·java-ee
z千鑫5 小时前
【C/C++】数据库链接入门教程:从零开始的详细指南!MySQL集成与操作
c语言·数据库·c++
开敲5 小时前
【MySQL】MySQL数据库基础
数据库·mysql
痞老板A小安装C46 小时前
Redis 过期策略和内存淘汰策略
数据库·redis·缓存
陈燚_重生之又为程序员7 小时前
梧桐数据库的高效索引技术分析
数据库
hellolio8 小时前
PostgreSQL详细安装教程
数据库·postgresql
鳄鱼的眼泪18 小时前
mysql深度分页优化
数据库·mysql
yava_free8 小时前
介绍一下mysql binlog查看指定数据库的方法
java·数据库·mysql
漫天转悠8 小时前
MySQL中in和exists的区别
数据库·mysql