drf序列化

在前后端不分离的项目中,可以使用Django自带的forms组件进行数据验证,也可以使用Django自带的序列化组件对模型表数据进行序列化。

那么在前后端分离的项目中,drf也提供了数据验证与序列化,相比于Django原生的序列化它更加强大与易用。

准备工作

注册drf

首先第一步,我们需要在项目全局文件夹中注册drf

INSTALLED_APPS = [
'app01.apps.App01Config',
'rest_framework', # 注册drf
]

模型表

下面是项目中的模型表。

学生和班级是一对多

班级和老师是多对多

班级和班主任是一对一

from django.db import models

# Create your models here.

class Student(models.Model):
student_id = models.AutoField(primary_key=True, verbose_name="学生编号")
student_name = models.CharField(max_length=8, verbose_name="学生姓名")
student_gender = models.BooleanField(
choices=([0, "male"], [1, "female"]), default=0, verbose_name="学生性别")
student_class = models.ForeignKey(
to="Classes", verbose_name="所属班级", on_delete=models.CASCADE) # 一个班级多个学生 def __str__(self):
return self.student_name class Meta:
db_table = ''
managed = True
verbose_name = 'Student'
verbose_name_plural = 'Students' class Classes(models.Model):
class_id = models.AutoField(primary_key=True, verbose_name="班级编号")
class_name = models.CharField(max_length=8, verbose_name="班级名称")
class_teacher = models.OneToOneField(
to="Teacher", verbose_name="班主任", on_delete=models.CASCADE) # 一个班级只有一个班主任 def __str__(self):
return self.class_name class Meta:
db_table = ''
managed = True
verbose_name = 'Classes'
verbose_name_plural = 'Classess' class Teacher(models.Model):
teacher_id = models.AutoField(primary_key=True, verbose_name="教师编号")
teacher_name = models.CharField(max_length=8, verbose_name="教师姓名")
teacher_class = models.ManyToManyField(
to="Classes", verbose_name="任教班级") # 一个班级中可有多个老师,一个老师也可以在多个班级中任教 def __str__(self):
return self.teacher_name class Meta:
db_table = ''
managed = True
verbose_name = 'Teacher'
verbose_name_plural = 'Teachers'

数据展示

学生信息如下:

mysql> select * from app01_student;

+------------+--------------+----------------+------------------+
| student_id | student_name | student_gender | student_class_id |
+------------+--------------+----------------+------------------+
| 1 | 学生1 | 1 | 1 |
| 2 | 学生2 | 1 | 2 |
| 3 | 学生3 | 1 | 2 |
| 4 | 学生4 | 0 | 1 |
+------------+--------------+----------------+------------------+

教师信息如下:

mysql> select * from app01_teacher;
+------------+--------------+
| teacher_id | teacher_name |
+------------+--------------+
| 1 | 王老师 |
| 2 | 李老师 |
| 3 | 张老师 |
+------------+--------------+

班级信息如下:

mysql> select * from app01_classes;
+----------+--------------+------------------+
| class_id | class_name | class_teacher_id |
+----------+--------------+------------------+
| 1 | 高一一班 | 1 |
| 2 | 高二一班 | 2 |
+----------+--------------+------------------+

教师与班级关系如下:

mysql> select * from app01_teacher_teacher_class;

+----+------------+------------+
| id | teacher_id | classes_id |
+----+------------+------------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 2 | 2 |
| 5 | 3 | 1 |
| 6 | 3 | 2 |
+----+------------+------------+

url书写

接下来书写url,以查询学生模型表为例,为了符合framework规范,所以要有一个有名分组来接收可能获取/修改/删除的编号。

from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/students/(?P<sid>\d+)?', views.Student.as_view()),
] # 添加问号,代表可有,可没有

自定义序列器

使用自定义序列器。可以更加灵活的使用序列化及反序列化。也是推荐使用的方式。

创建序列类

序列类的作用如下:

  1. 序列化时,可选择序列化的模型表字段
  2. 反序列化时,可选择对数据验证的规则,类似于forms组件
from .models import Student
from rest_framework import serializers class StudentSerializer(serializers.Serializer):
student_id = serializers.CharField()
student_name = serializers.CharField()
student_gender = serializers.BooleanField()
student_class = serializers.CharField()

进行序列化

接下来进行序列化,首先要书写视图函数。

由于我们每次都需要返回一个状态码,以及内容包装,所以可以创建一个构建返回内容的类。

第一步要将序列化类导入,在进行序列化的时候将需要序列化的数据对象进行传入。

当序列化完成后,得到一个序列化对象,它有一个data属性,是已经序列化完成的一个字典。

把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse

序列化单个对象,不需要在序列化时指定参数many

序列化多个对象,需要在序列化时指定参数many

from rest_framework.views import APIView
from rest_framework.views import Request
from rest_framework.views import Response # 通过Response返回
from app01 import models
from app01.drf_ser import StudentSerializer class returnData(object):
# 构建返回的信息
def __init__(self):
self.status = 100 # 100代表成功,200代表失败
self.message = None # 返回的信息
self.data = None # 序列化后的结果 def get_dict(self):
return self.__dict__ @property
def data(self):
return self.data @data.setter
def data(self, value):
self.__dict__["data"] = value class Student(APIView):
def get(self, request, sid=None):
# 初始化返回信息
res = returnData()
if sid:
# 代表获取单个
obj = models.Student.objects.filter(pk=sid).first()
if obj:
serializer_result = StudentSerializer(obj)
res.data = serializer_result.data
else:
res.message = "没有该学生"
res.status = 200
return Response(res.get_dict()) else:
# 代表获取所有
obj_queryset = models.Student.objects.all() if obj_queryset:
serializer_result = StudentSerializer(
obj_queryset, many=True) # many=True代表获取多条
res.data = serializer_result.data else:
res.message = "暂时没有任何学生"
res.status = 200
return Response(res.get_dict()) def post(self, request, sid):
# 新增
pass def delete(self, request, sid):
# 删除
pass def patch(self, request, sid):
# 修改
pass

序列化时,只关心怎样将数据返回给页面。

所以我们只做GET部分,注意用if判断来判定是获取所有,还是获取单个。

以下是获取全部的结果:

# http://127.0.0.1:8000/api/students/

{
"status": 100,
"message": null,
"data": [
{
"student_id": "1",
"student_name": "学生1",
"student_gender": true,
"student_class": "高一一班"
},
{
"student_id": "2",
"student_name": "学生2",
"student_gender": true,
"student_class": "高二一班"
},
{
"student_id": "3",
"student_name": "学生3",
"student_gender": true,
"student_class": "高二一班"
},
{
"student_id": "4",
"student_name": "学生4",
"student_gender": false,
"student_class": "高一一班"
}
]
}

以下是获取单条的结果:

{
"status": 100,
"message": null,
"data": {
"student_id": "1",
"student_name": "学生1",
"student_gender": true,
"student_class": "高一一班"
}
}

当获取出错时,message中就会存在错误信息:

{
"status": 200,
"message": "没有该学生",
"data": null
}

反序列化参数介绍

反序列化通常是使用POST/PATCH插入或更新数据时使用,收集到页面传递的数据,进行反序列化后写入数据库中。

当进行反序列化时,可以在序列类中指定一些参数,对将要反序列化写入模型表的字段进行检查。

参数 描述
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最小值
min_value 最大值
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典

初此之外,还有两个比较特殊的参数:

参数 描述
read_only 表明该字段仅用于序列化输出,默认False,如果设置成True,postman中可以看到该字段,修改时,不需要传该字段
write_only 表明该字段仅用于反序列化输入,默认False,如果设置成True,postman中看不到该字段,修改时,该字段需要传

反序列化钩子

validate_字段名是局部钩子

validate是全局钩子

如果要在钩子中抛出异常,则需要导入异常模块。

from rest_framework import exceptions
# raise exceptions.ValidationError('异常了')

如下是局部钩子的使用示例,因为页面提交过来的数据关于一对多中的班级字段是字符串,所以我们需要将字符串变为模型表对象,方便后面的创建以及更新。

    def validate_student_class(self, data):
# data是提交过来的这一个字段的数据
class_obj = Classes.objects.filter(class_name=data).first()
if not class_obj:
raise exceptions.ValidationError("班级不存在")
data = class_obj # 将字符串替换为对象
return data

全局钩子使用也是一样。如下,验证学生名和班级名是否相同,如果相同则抛出异常

    def validate(self, validate_data):
student_name = validate_data.get("student_name")
class_obj = validate_data.get("student_class") # 由于局部钩子中,这里被替换成了对象,所以我们拿到对象不能直接作比较
if student_name == class_obj.class_name:
raise exceptions.ValidationError("学生名不能和班级名相同")
return validate_data

create&update

在进行反序列化时,必须在序列类中覆写create()方法以及update()方法。

其中create()方法针对的是新增用户,而update()方法针对的是更新用户。

如果不进行覆写,则会抛出异常,这是因为作者在源码中做了接口约束的设置:

def update(self, instance, validated_data):
raise NotImplementedError('`update()` must be implemented.') def create(self, validated_data):
raise NotImplementedError('`create()` must be implemented.')

反序列化案例

了解了上面反序列化需要注意的事项后,开始书写视图函数中的POST/PATCH方法。

下面是创建一个学生的例子:

def post(self, request):
# 初始化返回信息
res = returnData()
serializer_result = StudentSerializer(data=request.data) # 传入request.data即可。这里一定要使用关键字传参!!!
if serializer_result.is_valid():
# 验证通过了
serializer_result.save() # 保存序列化实例类
res.data = serializer_result.data # 遵循规范,返回新增的数据
else:
# 验证没通过
res.status = 200
res.message = "数据校验失败"
res.data = serializer_result.errors # 添加错误信息 return Response(res.get_dict())

重写create()方法并返回:

    def create(self, validated_data):
instance = Student.objects.create(**validated_data)
return instance # 这里返回的信息会返回到序列类对象的data属性中

下面是修改一个学生的例子:

    def patch(self, request, sid):
# 初始化返回信息
res = returnData()
obj = models.Student.objects.filter(pk=sid).first()
if obj:
serializer_result = StudentSerializer(instance=obj, data=request.data) # 需要传入的参数,记录本身,新的数据
if serializer_result.is_valid():
# 验证通过了
serializer_result.save() # 保存序列化实例类
res.data = serializer_result.data # 遵循规范,返回修改的数据
else:
# 验证没通过
res.status = 200
res.message = "数据校验失败"
res.data = serializer_result.errors # 添加错误信息
else:
res.status = 200
res.message = "用户不存在" return Response(res.get_dict())

重写update()方法并返回:

    def update(self, instance, validated_data):

        # 对数据做更新后再返回
# validated_data中取出str的键,然后用反射进行设置 for k, v in validated_data.items():
setattr(instance, k, v)
instance.save()
return instance

全部代码

views.py

from rest_framework.views import APIView
from rest_framework.views import Request
from rest_framework.views import Response # 通过Response返回
from app01 import models
from app01.drf_ser import StudentSerializer # 导入自定义序列类 class returnData(object):
# 构建返回的信息
def __init__(self):
self.status = 100 # 100代表成功,200代表失败
self.message = None # 返回的信息
self.data = None # 序列化后的结果 def get_dict(self):
return self.__dict__ @property
def data(self):
return self.data @data.setter
def data(self, value):
self.__dict__["data"] = value class Student(APIView):
def get(self, request, sid=None):
# 初始化返回信息
res = returnData()
if sid:
# 代表获取单个
obj = models.Student.objects.filter(pk=sid).first()
if obj:
serializer_result = StudentSerializer(obj)
res.data = serializer_result.data
else:
res.message = "没有该学生"
res.status = 200
return Response(res.get_dict()) else:
# 代表获取所有
obj_queryset = models.Student.objects.all() if obj_queryset:
serializer_result = StudentSerializer(
obj_queryset, many=True) # many=True代表获取多条
res.data = serializer_result.data else:
res.message = "暂时没有任何学生"
res.status = 200
return Response(res.get_dict()) def post(self, request):
# 初始化返回信息
res = returnData()
serializer_result = StudentSerializer(
data=request.data) # 传入request.data即可
if serializer_result.is_valid():
# 验证通过了
serializer_result.save() # 保存序列化实例类
res.data = serializer_result.data # 遵循规范,返回新增的数据
else:
# 验证没通过
res.status = 200
res.message = "数据校验失败"
res.data = serializer_result.errors # 添加错误信息 return Response(res.get_dict()) def delete(self, request):
# 删除
pass def patch(self, request, sid):
# 初始化返回信息
res = returnData()
obj = models.Student.objects.filter(pk=sid).first()
if obj:
serializer_result = StudentSerializer(instance=obj, data=request.data) # 需要传入的参数,记录本身,新的数据
if serializer_result.is_valid():
# 验证通过了
serializer_result.save() # 保存序列化实例类
res.data = serializer_result.data # 遵循规范,返回修改的数据
else:
# 验证没通过
res.status = 200
res.message = "数据校验失败"
res.data = serializer_result.errors # 添加错误信息
else:
res.status = 200
res.message = "用户不存在" return Response(res.get_dict())

自定义序列类

from .models import Student
from .models import Classes
from rest_framework import serializers
from rest_framework import exceptions class StudentSerializer(serializers.Serializer):
student_id = serializers.CharField(read_only=True) # 创建/修改时不用传该字段,但是页面可以看见
# 相反的,如果是wrtie_only则代表页面看不见,但是你要传
student_name = serializers.CharField(max_length=8, min_length=3)
student_gender = serializers.BooleanField()
student_class = serializers.CharField() def validate_student_class(self, data):
class_obj = Classes.objects.filter(class_name=data).first()
if not class_obj:
raise exceptions.ValidationError("班级不存在")
data = class_obj # 将字符串替换为对象
return data def validate(self, validate_data):
student_name = validate_data.get("student_name")
class_obj = validate_data.get("student_class")
if student_name == class_obj.class_name:
raise exceptions.ValidationError("学生名不能和班级名相同")
return validate_data def create(self, validated_data):
instance = Student.objects.create(**validated_data)
return instance # 这里返回的信息会返回到序列类对象的data属性中 def update(self, instance, validated_data):
# 对数据做更新后再返回
# validated_data中取出str的键,然后用反射进行设置
for k, v in validated_data.items():
setattr(instance, k, v)
instance.save()
return instance

模型表序列器

模型表的序列器定制化比较低,但是使用较为方便。

能够非常快速的开发接口。

创建序列类

创建序列器:

# 模型表序列器
class StudentModelSerializer(serializers.ModelSerializer):
class Meta:
model = Student # 对应上models.py中的模型
fields = '__all__' # 序列化所有字段 # fields=('student_id','student_name') # 只序列化指定的字段
# exclude=('student_id',) # 跟fields不能同时都写,写谁,就表示排除谁
# read_only_fields=('student_id',)
# write_only_fields=('student_class',) # 弃用了,使用extra_kwargs
# extra_kwargs = { # 类似于这种形式 student_name=serializers.CharField(max_length=16,min_length=4)
# 'student_name': {'write_only': True},
# } def validate_student_class(self, data):
class_obj = Classes.objects.filter(class_name=data).first()
if not class_obj:
raise exceptions.ValidationError("班级不存在")
data = class_obj # 将字符串替换为对象
return data def validate(self, validate_data):
student_name = validate_data.get("student_name")
class_obj = validate_data.get("student_class")
print(class_obj)
if student_name == class_obj.class_name:
raise exceptions.ValidationError("学生名不能和班级名相同")
return validate_data

基本使用

其他使用一模一样,注意在反序列化时不需要重写create()updata()方法了。

以下是视图API接口中的代码,只需要把原本使用自定义序列器的地方修改成使用模型表序列器即可。

from rest_framework.views import APIView
from rest_framework.views import Request
from rest_framework.views import Response # 通过Response返回
from app01 import models
# from app01.drf_ser import StudentModelSerializer
from app01.drf_ser import StudentModelSerializer class returnData(object):
# 构建返回的信息
def __init__(self):
self.status = 100 # 100代表成功,200代表失败
self.message = None # 返回的信息
self.data = None # 序列化后的结果 def get_dict(self):
return self.__dict__ @property
def data(self):
return self.data @data.setter
def data(self, value):
self.__dict__["data"] = value class Student(APIView):
def get(self, request, sid=None):
# 初始化返回信息
res = returnData()
if sid:
# 代表获取单个
obj = models.Student.objects.filter(pk=sid).first()
if obj:
serializer_result = StudentModelSerializer(obj)
res.data = serializer_result.data
else:
res.message = "没有该学生"
res.status = 200
return Response(res.get_dict()) else:
# 代表获取所有
obj_queryset = models.Student.objects.all() if obj_queryset:
serializer_result = StudentModelSerializer(
obj_queryset, many=True) # many=True代表获取多条
res.data = serializer_result.data else:
res.message = "暂时没有任何学生"
res.status = 200
return Response(res.get_dict()) def post(self, request):
# 初始化返回信息
res = returnData()
serializer_result = StudentModelSerializer(
data=request.data) # 传入request.data即可
if serializer_result.is_valid():
# 验证通过了
serializer_result.save() # 保存序列化实例类
res.data = serializer_result.data # 遵循规范,返回新增的数据
else:
# 验证没通过
res.status = 200
res.message = "数据校验失败"
res.data = serializer_result.errors # 添加错误信息 return Response(res.get_dict()) def delete(self, request):
# 删除
pass def patch(self, request, sid):
# 初始化返回信息
res = returnData()
obj = models.Student.objects.filter(pk=sid).first()
if obj:
serializer_result = StudentModelSerializer(instance=obj, data=request.data) # 需要传入的参数,记录本身,新的数据
if serializer_result.is_valid():
# 验证通过了
serializer_result.save() # 保存序列化实例类
res.data = serializer_result.data # 遵循规范,返回修改的数据
else:
# 验证没通过
res.status = 200
res.message = "数据校验失败"
res.data = serializer_result.errors # 添加错误信息
else:
res.status = 200
res.message = "用户不存在" return Response(res.get_dict())

多关系子序列化

source参数

source参数的使用:

  1. 可以改字段名字 xxxx=serializers.CharField(source='student_name')
  2. 可以.跨表 cls=serializers.CharField(source='student_class.name') # 相当于 student_student_class__name进行数据获取
  3. 可以执行方法pub_date=serializers.CharField(source='test') test是Student表模型中的方法(可忽略,这个相当于验证方法。还不如使用钩子函数)

该参数最重要的两点,source中写的是什么,就从哪里取数据,即展示的就是什么。当反序列化时,不再按照序列器类的字段名进行反序列化,而是按照该参数进行反序列化填值。

看一下,我要让student_name显示的不是学生的名字,而是班主任的名字,就用到了第一条和第二条,跨表,显示数据,可以这样设置。

class StudentSerializer(serializers.Serializer):
student_id = serializers.CharField(read_only=True) # 创建/修改时不用传该字段,但是页面可以看见
student_name = serializers.CharField(max_length=8, min_length=3,source="student_class.class_teacher.teacher_name") # 相当于:Student.objects.filter(pk=传入的id).values_list("student_class__class_teacher__teacher_name")[0][0]
student_gender = serializers.BooleanField(source="student_gender")
student_class = serializers.CharField()

当进行GET请求后,将会看到下面的结果:

# http://127.0.0.1:8000/api/students/5/

{
"status": 100,
"message": null,
"data": {
"student_id": "5",
"student_name": "王老师", # 所以说,该参数后面写的是什么,展示的就是什么。
"student_gender": false,
"student_class": "高一一班"
}
}

示例演示,我们通常会将展示的数据名字进行重命名,区分开与数据库存储的字段名,这样做更加安全,所以可以进行如下设置:

from .models import Student
from .models import Classes
from rest_framework import serializers
from rest_framework import exceptions class StudentSerializer(serializers.Serializer):
sid = serializers.CharField(read_only=True,source="student_id") # 创建/修改时不用传该字段,但是页面可以看见
name = serializers.CharField(max_length=8, min_length=3,source="student_name")
gender = serializers.BooleanField(source="student_gender")
classes = serializers.CharField(source="student_class") # source中写的是什么,就从哪里取数据 def validate_classes(self, data):
# data是提交过来的这一个字段的数据
class_obj = Classes.objects.filter(class_name=data).first()
if not class_obj:
raise exceptions.ValidationError("班级不存在")
data = class_obj # 将字符串替换为对象
return data def create(self, validated_data):
instance = Student.objects.create(**validated_data)
return instance # 这里返回的信息会返回到序列类对象的data属性中 def update(self, instance, validated_data):
# 对数据做更新后再返回
# validated_data中取出str的键,然后用反射进行设置
for k, v in validated_data.items():
setattr(instance, k, v)
instance.save()
return instance
{
"status": 100,
"message": null,
"data": {
"sid": "5",
"name": "修改学生5",
"gender": false,
"classes": "高一一班"
}
}

SerializerMethodField字段

它需要有个配套方法,方法名叫get_字段名,返回值就是要显示的东西。

比如,我们想查看每个学生都有那些老师在教授,就可以使用该参数:

class StudentSerializer(serializers.Serializer):
sid = serializers.CharField(read_only=True,source="student_id") # 创建/修改时不用传该字段,但是页面可以看见
name = serializers.CharField(max_length=8, min_length=3,source="student_name")
gender = serializers.BooleanField(source="student_gender")
classes = serializers.CharField(source="student_class") # 现在,我要让他显示的是班级编号,而不再是班级名称了
students = serializers.SerializerMethodField() def get_students(self,instance):
teacher_queryset = instance.student_class.teacher_set.values("pk","teacher_name")
return teacher_queryset

最后的结果如下:

# http://127.0.0.1:8000/api/students/5/

{
"status": 100,
"message": null,
"data": {
"sid": "5",
"name": "修改学生5",
"gender": false,
"classes": "高一一班",
"students": [
{
"pk": 1,
"teacher_name": "王老师"
},
{
"pk": 2,
"teacher_name": "李老师"
},
{
"pk": 3,
"teacher_name": "张老师"
}
]
}
}

drf Serializer基本使用的更多相关文章

  1. drf Serializer使用

    drf序列化 在前后端不分离的项目中,可以使用Django自带的forms组件进行数据验证,也可以使用Django自带的序列化组件对模型表数据进行序列化. 那么在前后端分离的项目中,drf也提供了数据 ...

  2. django restframework Serializer field

    SerializerMethodField 这是一个只读字段.它通过调用它所连接的序列化类的方法来获得它的值.它可用于将任何类型的数据添加到对象的序列化表示中. 签名: SerializerMetho ...

  3. restful(1):序列化

    restful协议中,一切皆是资源,操作只是请求方式 model_to_dict()方法: from django.forms.models import model_to_dict obj = Pu ...

  4. drf-Serializers

    What is serializers? serializers主要作用是将原生的Python数据类型(如 model querysets )转换为web中通用的JSON,XML或其他内容类型. DR ...

  5. 写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用

    写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用 一.了解什么是DRF DRF: Django REST framework Django REST framew ...

  6. Django框架(十八)—— drf:序列化组件(serializer)

    序列化组件 # 模型层 from django.db import models class Book(models.Model): nid = models.AutoField(primary_ke ...

  7. Django框架之DRF APIView Serializer

    一.APIView 我们在使用DjangoRestfulFramework的时候会将每个视图类继承APIView,取代原生Django的View类 APIView的流程分析: rest_framewo ...

  8. DRF框架(二)——解析模块(parsers)、异常模块(exception_handler)、响应模块(Response)、三大序列化组件介绍、Serializer组件(序列化与反序列化使用)

    解析模块 为什么要配置解析模块 1)drf给我们提供了多种解析数据包方式的解析类 form-data/urlencoded/json 2)我们可以通过配置来控制前台提交的哪些格式的数据后台在解析,哪些 ...

  9. drf框架 - 序列化组件 | Serializer

    序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 序列化与反序列化 序列化: 将对象序列化成字符串用户传输 ...

  10. 第三章、drf框架 - 序列化组件 | Serializer

    目录 第三章.drf框架 - 序列化组件 | Serializer 序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer( ...

随机推荐

  1. 滴水2.c++构造 与 继承

    1.构造函数特点 2.析构函数的特点: 析构函数前面必须有~ 3.继承 一个子类可以有多个父类 作业1. #include<stdio.h> struct DateInfo { int y ...

  2. B端业务中仓库标签打印系统设计方案

    需求背景: 仓库在给客户货物打包途中需要在包裹上贴标签,在客户比较多且标签样式多样化的前提下,给仓库人员带来了工作量,为了节约仓库人员工作流程时间,公司开发了一套标签管理系统: 前提条件:选择专属打印 ...

  3. EMBARK研究: 依那西普治疗早期nr-axSpA达48周的临床和MRI疗效

    关键词: 放射学阴性中轴型SpA; TNF拮抗剂; 磁共振影像 EMBARK研究48周结果: 依那西普治疗早期放射学阴性中轴型SpA患者的临床与MRI疗效 电邮发布日期:2016年1月25日 文献: ...

  4. Word 表格对文字、图文进行排版

    在以前,Web 前端工程师利用 <table /> 元素对网页布局进行排版,但是如今却不推荐此元素排版了,而是改用 <div /> 元素和 CSS 弹性布局(或网格布局)对网页 ...

  5. kingbase字符类数据类型和oracle字符类型的区别

    为兼容Oracle的数据类型,KingbaseES扩展了Oracle的NUMBER.VARCHAR2.CHAR(n)和DATE类型.该措施使得移植Oracle的Create Table等DDL语句时, ...

  6. 结合ChatGPT体验新必应new bing 的惊喜:这是我第一次使用的感受

    前言 最近相信大家都被 ChatGPT 刷屏了,它的爆火大家是有目共睹的,微软的新必应(New Bing) 是结合了比 ChatGPT 更强大的新一代 OpenAI 语言模式,接下来我们一起来&quo ...

  7. Canonical为所有支持的Ubuntu LTS系统发布了新的Linux内核更新

    Canonical近日为所有支持的Ubuntu LTS系统发布了新的Linux内核更新,以解决总共19个安全漏洞. 新的Ubuntu内核更新仅适用于长期支持的Ubuntu系统,包括Ubuntu 22. ...

  8. 阿里云服务器 jdk1.8 安装配置

     阿里云服务器 jdk1.8 安装配置 下载/上传 jdk安装包 解压到指定目录 重命名解压后的文件夹名称 配置环境变量 验证JAVA环境是否安装成功 step 0.安装包准备 1 wget --no ...

  9. app内嵌H5踩坑

    内嵌的H5是用的vue2版本开发的,期间有很多的坑要踩: 1.调用app返回上一个页面不触发页面的onmouted和window.onPageShow app返回上一个页面调用的方法并不会出发vue的 ...

  10. 蓝牙mesh组网实战(智能家居应用)

    目录 蓝牙mesh组网目前存在有入门门槛高的问题,比如,嵌入式工程师需要考虑到标准mesh模型的兼容,app开发工程师需要了解mesh协议栈才能直接走mesh与芯片通信.而沁恒官方提供的透传模型简洁易 ...