DRF 序列化器
Serializer
DRF 序列化器用于处理 Django 模型实例与 JSON 格式数据的相互转换,比原生 Django 更简洁
建议以模块化的形式组织定义在自定义应用目录下
[项目目录]
├─ manage.py
│
├─ [主应用]/
│ └─ ...
│
└─ [自定义应用名]/
├─ ...
└─ serializers/
├─ __init__.py
├─ [序列化器1].py
├─ [序列化器2].py
└─ ...
创建
序列化器是个类,自定义序列化器类通常命名为模型名Serializer
序列化器会自动映射模型中的字段到响应数据,可通过fields
或exclude
属性选择具体的字段
py
from rest_framework import serializers
from .models import 自定义模型类
class 自定义序列化器类(serializers.ModelSerializer):
响应数据中的字段1 = serializers.字段类()
响应数据中的字段2 = serializers.字段类()
class Meta:
model = 自定义模型类
fields = ("模型类中的字段1", "模型类中的字段2") # exclude 与 fields 二选一
exclude = ("模型类中的字段1", "模型类中的字段2") # exclude 与 fields 二选一
read_only_fields = ("模型类中的字段1", "模型类中的字段2")
例子:基于模型类创建一个简单的序列化器类
py
from rest_framework import serializers
from .models import Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
exclude = ("id",)
py
from django.db import models
class Student(models.Model):
name = models.CharField(max_length=36, verbose_name="学生姓名", help_text="姓名")
score = models.FloatField(verbose_name="学生分数", help_text="分数")
updated_at = models.DateTimeField(auto_now_add=True, verbose_name="更新时间")
class Meta:
verbose_name = "学生信息"
verbose_name_plural = verbose_name
ordering = ("score",)
def __str__(self):
return self.name
[项目目录]
├─ manage.py
│
├─ [主应用]/
│ └─ ...
│
└─ [应用名]
├─ admin.py
├─ views.py
├─ models.py
├─ serializers.py
└─ ...
序列化与反序列化
py
# 获取数据库表中所有数据 ( 列表形式 )
# --------------------------------------------------------------------------------
模型类实例 = 模型类.objects.all()
序列化器类实例 = 序列化器类(instance=模型类实例, many=True)
数据 = 序列化器类实例.data
# 获取数据库表中指定数据 ( 字典形式 )
# --------------------------------------------------------------------------------
try:
模型类实例 = 模型类.objects.get(字段=值)
except 模型类.DoesNotExist:
# ...
else:
序列化器类实例 = 序列化器类(模型类实例)
数据 = 序列化器类实例.data
# 向数据库表中创建数据
# --------------------------------------------------------------------------------
数据 = {"字段1": 值, "字段2": 值}
序列化器类实例 = 序列化器类(data=数据)
# 更新数据库表中的数据
# --------------------------------------------------------------------------------
try:
模型类实例 = 模型类.objects.get(字段=值)
except 模型类.DoesNotExist:
# ...
else:
数据 = {"字段1": 值, "字段2": 值}
序列化器类实例 = 序列化器类(模型类实例, data=数据, partial=True)
if 序列化器类实例.is_valid():
序列化器类实例.save()
# 从数据库表中删除数据
# --------------------------------------------------------------------------------
try:
模型类实例 = 模型类.objects.get(字段=值)
except 模型类.DoesNotExist:
# ...
else:
模型类实例.delete()
例子:( CBV + APIView ) 自定义 GET 请求返回所有数据与指定数据
py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Student
from .serializers import StudentSerializer
class StudentListView(APIView):
def get(self, requests):
students = Student.objects.all()
serializer = StudentSerializer(instance=students, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)
class StudentDetailView(APIView):
def get(self, requests, **kwargs):
try:
student_id = kwargs.get("id")
student = Student.objects.get(id=student_id)
except Student.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
else:
serializer = StudentSerializer(student)
return Response(data=serializer.data, status=status.HTTP_200_OK)
py
from django.db import models
from django.conf import settings
class Student(models.Model):
name = models.CharField(max_length=36, verbose_name="学生姓名", help_text="姓名")
score = models.FloatField(verbose_name="学生分数", help_text="分数")
updated_at = models.DateTimeField(auto_now_add=True, verbose_name="更新时间")
class Meta:
verbose_name = "学生信息"
verbose_name_plural = verbose_name
ordering = ("score",)
def __str__(self):
return self.name
py
from rest_framework import serializers
from .models import Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = ("name", "score", "updated_at")
py
from django.urls import path
from .views import StudentListView, StudentDetailView
urlpatterns = [
path("students", StudentListView.as_view(), name="students"),
path("student/<int:id>", StudentDetailView.as_view(), name="student_detail"),
]
zsh
% curl -X GET http://127.0.0.1:8000/students \
-H "X-CSRFToken: 4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp" \
-b "csrftoken=4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp; sessionid=yr0q1nngcevqcgigakgfnniip3lff3st"
# [{"name":"Andy","score":98.0,"updated_at":"2024-10-19T02:16:20+0000"}]
% curl -X GET http://127.0.0.1:8000/student/1 \
-H "X-CSRFToken: 4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp" \
-b "csrftoken=4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp; sessionid=yr0q1nngcevqcgigakgfnniip3lff3st"
# {"name":"Andy","score":98.0,"updated_at":"2024-10-19T02:16:20+0000"}
[项目目录]
├─ manage.py
│
├─ [主应用]/
│ └─ ...
│
└─ student/
├─ migrations/
├─ urls.py
├─ models.py
├─ serializers.py
├─ views.py
└─ ...
例子:( CBV + APIView ) 自定义 POST 请求创建数据
py
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Student
from .serializers import StudentSerializer
class CreateStudentView(APIView):
def post(self, request):
serializer = StudentSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
py
from django.db import models
from django.conf import settings
class Student(models.Model):
name = models.CharField(max_length=36, verbose_name="学生姓名", help_text="姓名")
score = models.FloatField(verbose_name="学生分数", help_text="分数")
updated_at = models.DateTimeField(auto_now_add=True, verbose_name="更新时间")
class Meta:
verbose_name = "学生信息"
verbose_name_plural = verbose_name
ordering = ("score",)
def __str__(self):
return self.name
py
from rest_framework import serializers
from .models import Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = ("name", "score", "updated_at")
py
from django.urls import path
from .views import CreateStudentView
urlpatterns = [
path("student/create", CreateStudentView.as_view(), name="student_create"),
]
zsh
% curl -X POST http://127.0.0.1:8000/student/create \
-H "X-CSRFToken: 4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp" \
-b "csrftoken=4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp; sessionid=yr0q1nngcevqcgigakgfnniip3lff3st" \
-H "Content-Type: application/json" \
-d '{"name":"Tom", "score":48 }'
# {"name":"Tom","score":48.0,"updated_at":"2024-10-19T06:27:25+0000"}
% curl -X POST http://127.0.0.1:8000/student/create \
-H "X-CSRFToken: 4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp" \
-b "csrftoken=4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp; sessionid=yr0q1nngcevqcgigakgfnniip3lff3st" \
-H "Content-Type: application/json" \
-d '{"name":"Amy"}'
# {"score":["This field is required."]}
[项目目录]
├─ manage.py
│
├─ [主应用]/
│ └─ ...
│
└─ student/
├─ migrations/
├─ urls.py
├─ models.py
├─ serializers.py
├─ views.py
└─ ...
例子:( CBV + APIView ) 自定义 PATCH 请求更新部分数据
py
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Student
from .serializers import StudentSerializer
class StudentView(APIView):
def patch(self, request, **kwargs):
try:
student_id = kwargs.get("id")
student = Student.objects.get(id=student_id)
except Student.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
else:
serializer = StudentSerializer(student, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
py
from django.db import models
from django.conf import settings
class Student(models.Model):
name = models.CharField(max_length=36, verbose_name="学生姓名", help_text="姓名")
score = models.FloatField(verbose_name="学生分数", help_text="分数")
updated_at = models.DateTimeField(auto_now_add=True, verbose_name="更新时间")
class Meta:
verbose_name = "学生信息"
verbose_name_plural = verbose_name
ordering = ("score",)
def __str__(self):
return self.name
py
from rest_framework import serializers
from .models import Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = ("name", "score", "updated_at")
py
from django.urls import path
from .views import StudentView
urlpatterns = [
path("student/<int:id>", StudentView.as_view(), name="student_detail"),
]
zsh
% curl -X PATCH http://127.0.0.1:8000/student/7 \
-H "X-CSRFToken: 4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp" \
-b "csrftoken=4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp; sessionid=yr0q1nngcevqcgigakgfnniip3lff3st" \
-H "Content-Type: application/json" \
-d '{"name":"Tom", "score":68 }'
# {"name":"Tom","score":68.0,"updated_at":"2024-10-19T06:27:25+0000"}
[项目目录]
├─ manage.py
│
├─ [主应用]/
│ └─ ...
│
└─ student/
├─ migrations/
├─ urls.py
├─ models.py
├─ serializers.py
├─ views.py
└─ ...
例子:( CBV + APIView ) 自定义 DELETE 请求删除数据
py
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Student
from .serializers import StudentSerializer
class StudentView(APIView):
def delete(self, requests, **kwargs):
try:
student_id = kwargs.get("id")
student = Student.objects.get(id=student_id)
except Student.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
else:
student.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
py
from django.db import models
from django.conf import settings
class Student(models.Model):
name = models.CharField(max_length=36, verbose_name="学生姓名", help_text="姓名")
score = models.FloatField(verbose_name="学生分数", help_text="分数")
updated_at = models.DateTimeField(auto_now_add=True, verbose_name="更新时间")
class Meta:
verbose_name = "学生信息"
verbose_name_plural = verbose_name
ordering = ("score",)
def __str__(self):
return self.name
py
from rest_framework import serializers
from .models import Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = ("name", "score", "updated_at")
py
from django.urls import path
from .views import StudentView
urlpatterns = [
path("student/<int:id>", StudentView.as_view(), name="student_detail"),
]
zsh
% curl -X DELETE http://127.0.0.1:8000/student/7 \
-H "X-CSRFToken: 4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp" \
-b "csrftoken=4lxzaMWFWm3BxKhcpOnNZKyWiptOJQGp; sessionid=yr0q1nngcevqcgigakgfnniip3lff3st"
[项目目录]
├─ manage.py
│
├─ [主应用]/
│ └─ ...
│
└─ student/
├─ migrations/
├─ urls.py
├─ models.py
├─ serializers.py
├─ views.py
└─ ...