DRF(一) 基础部分
1. 序列化
1.1 什么是序列化
对象转换为字符串用于传输,在前台使用
1.2 什么是反序列化
字符串转换为对象用于在后端环境使用
1.3 DRF序列化
序列化: model类对象转换为字符串用于传输,在前台使用
反序列化: 字符串转换为model类对象用于在后端环境使用
1.4 Model类
from django.db import models
class User(models.Model):
CHOICE_SEX = (
(0, '男'),
(1, '女')
)
name = models.CharField(max_length=32, verbose_name='姓名')
password = models.CharField(max_length=64, verbose_name='密码')
sex = models.SmallIntegerField(choices=CHOICE_SEX, default=0)
create_time = models.DateTimeField(auto_now_add=True, blank=True)
class Meta:
db_table = 'o_user' # 自定义创建的表名
verbose_name = '用户' # admin/xadmin 界面中显示的表名
verbose_name_plural = verbose_name # admin/xadmin 界面中显示的表名复数形式
def __str__(self):
return self.name
- 注册到admin
from django.contrib import admin
from api.models import User
admin.site.register(User)
- 创建数据库
python3 manage.py makemigrations api
python3 manage.py migrate
python3 manage.py createsuperuser
设置账号密码 chenjiawei520| 123456
1.5 路由分发
- 项目
urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls'))
]
- 应用(api)
urls.py
from django.urls import path
from api import views
urlpatterns = [
path('user/', views.UserView.as_view()),
]
1.6 视图函数
如果没有指定参数many=True
, 无论 user_list
是否有1条数据还是多条数据, 只要是个queryset对象, 就会报错
AttributeError: Got AttributeError when attempting to get a value for field name
on serializer UserSerializer
.
The serializer field might be named incorrectly and not match any attribute or key on the QuerySet
instance.
Original exception text was: 'QuerySet' object has no attribute 'name'.
如果是需要序列化数据, 但是将原数据user_list
赋值给参数data
, 则会报错
AssertionError: When a serializer is passed a data
keyword argument you must call .is_valid()
before attempting to access the serialized .data
representation.
You should either call .is_valid()
first, or access .initial_data
instead.
from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import User
from .Serializers import Userserializers
class UserView(APIView):
def get(self, request, *args, **kwargs):
user_list = User.objects.all()
print(user_list)
# 序列化model类的对象 - 序列化类(model类QuerySet对象)
# 序列化类的初始化方法(BaseSerializer)有三个参数
# instance 序列化 |data 反序列化 | many 是否有多个数据
# class BaseSerializer(Field):
# def __init__(self, instance=None, data=empty, **kwargs):
# self.instance = instance
# if data is not empty:
# self.initial_data = data
# self.partial = kwargs.pop('partial', False)
# self._context = kwargs.pop('context', {})
# kwargs.pop('many', None)
# super().__init__(**kwargs)
user_data = Userserializers(instance=user_list, many=True).data
return Response({
'code': 200,
'content': {
'msg': 'SUCCESS',
'data': user_data
}
})
1.7 序列化器
Serializers.py
序列化一个Model类对象就是序列化该类的每一个属性变成字符串给前端使用
from rest_framework import serializers
class Userserializers(serializers.Serializer):
# 序列化一个Model类对象就是序列化该类的每一个属性变成字符串给前端使用
name = serializers.CharField()
password = serializers.CharField()
create_time = serializers.DateTimeField()
gender = serializers.SerializerMethodField()
def get_gender(self, obj): # obj 为queryset 对象, 所以可以使用ORM方法操作
return obj.get_sex_display()
注意:
-
Model类与Serializer类是通过属性名建立关联的 - 属性名必须一样
-
不需要给前台的数据, 不需要提供该属性的序列化
-
serializers.SerializerMethodField()
可以产生自定义序列化属性(不需要和Model类属性同步)但要为其绑定一个提供值的函数,函数名为
get_属性(self,obj)
, 其中ob j为序列化数据的queryset对象,在这里就是user_list
1.8 反序列化器(插入数据)
Serializers.py
from rest_framework import serializers
from . import models
class Userserializers(serializers.Serializer):
# 序列化一个Model类对象就是序列化该类的每一个属性变成字符串给前端使用
name = serializers.CharField()
password = serializers.CharField()
create_time = serializers.DateTimeField()
gender = serializers.SerializerMethodField()
def get_gender(self, obj): # obj 为queryset 对象, 所以可以使用ORM方法操作
return obj.get_sex_display()
class UserDeserializers(serializers.Serializer):
name = serializers.CharField(max_length=32)
password = serializers.CharField(max_length=64)
sex = serializers.IntegerField()
create_time = serializers.DateTimeField(required=False)
# AssertionError: You cannot call `.save()` on a serializer with invalid data.
def save(self, **kwargs):
# 源码:
# class BaseSerializer(Field):
# @property
# def validated_data(self):
# if not hasattr(self, '_validated_data'):
# msg = 'You must call `.is_valid()` before accessing `.validated_data`.'
# raise AssertionError(msg)
# return self._validated_data
# 操作ORM
models.User.objects.create(**self.validated_data)
views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import User
from .Serializers import Userserializers, UserDeserializers
class UserView(APIView):
# 获取所有资源
def get(self, request, *args, **kwargs):
user_list = User.objects.all()
print(user_list)
user_data = Userserializers(instance=user_list, many=True).data
return Response({
'code': 200,
'content': {
'msg': 'SUCCESS',
'data': user_data
}
})
# 新增资源
def post(self, request, *args, **kwargs):
# AssertionError: Cannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance.
user_data = UserDeserializers(data=request.data)
# raise_exception=True 校验不通过报错信息在前台显示 报错信息是源码中默认的报错信息
result = user_data.is_valid(raise_exception=True)
if result:
user_data.save()
return Response('post ok')
1.9 反序列化器(自定义错误信息)
Serializers.py
from rest_framework import serializers
from . import models
class Userserializers(serializers.Serializer):
# 序列化一个Model类对象就是序列化该类的每一个属性变成字符串给前端使用
name = serializers.CharField()
password = serializers.CharField()
create_time = serializers.DateTimeField()
gender = serializers.SerializerMethodField()
def get_gender(self, obj): # obj 为queryset 对象, 所以可以使用ORM方法操作
return obj.get_sex_display()
class UserDeserializers(serializers.Serializer):
name = serializers.CharField(label="姓名", max_length=32, min_length=3, error_messages={
'max_length': '姓名太长',
'min_length': '姓名太短'
})
password = serializers.CharField(label='密码', max_length=64, min_length=3, error_messages={
'max_length': '密码太长',
'min_length': '密码太短'
})
sex = serializers.IntegerField()
create_time = serializers.DateTimeField(required=False)
# AssertionError: You cannot call `.save()` on a serializer with invalid data.
def create(self, validated_data):
# '`create()` did not return an object instance.'
# AssertionError: `create()` did not return an object instance.
#class BaseSerializer(Field):
# def create(self, validated_data):
# raise NotImplementedError('`create()` must be implemented.')
#
# def save(self, **kwargs):
# assert hasattr(self, '_errors'), (
# 'You must call `.is_valid()` before calling `.save()`.'
# )
#
# assert not self.errors, (
# 'You cannot call `.save()` on a serializer with invalid data.'
# )
#
# # Guard against incorrect use of `serializer.save(commit=False)`
# assert 'commit' not in kwargs, (
# "'commit' is not a valid keyword argument to the 'save()' method. "
# "If you need to access data before committing to the database then "
# "inspect 'serializer.validated_data' instead. "
# "You can also pass additional keyword arguments to 'save()' if you "
# "need to set extra attributes on the saved model instance. "
# "For example: 'serializer.save(owner=request.user)'.'"
# )
#
# assert not hasattr(self, '_data'), (
# "You cannot call `.save()` after accessing `serializer.data`."
# "If you need to access data before committing to the database then "
# "inspect 'serializer.validated_data' instead. "
# )
#
# validated_data = {**self.validated_data, **kwargs}
#
# if self.instance is not None:
# self.instance = self.update(self.instance, validated_data)
# assert self.instance is not None, (
# '`update()` did not return an object instance.'
# )
# else:
# self.instance = self.create(validated_data)
# assert self.instance is not None, (
# '`create()` did not return an object instance.'
# )
#
# return self.instance
print(validated_data)
self.instance = models.User.objects.create(**validated_data)
print(self.instance)
return self.instance
views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import User
from .Serializers import Userserializers, UserDeserializers
class UserView(APIView):
# 获取所有资源
def get(self, request, *args, **kwargs):
user_list = User.objects.all()
print(user_list)
user_data = Userserializers(instance=user_list, many=True).data
return Response({
'code': 200,
'content': {
'msg': 'SUCCESS',
'data': user_data
}
})
# 新增资源
def post(self, request, *args, **kwargs):
# AssertionError: Cannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance.
user_data = UserDeserializers(data=request.data)
# 校验不通过报错信息在前台显示
result = user_data.is_valid(raise_exception=True)
if result:
user_data.save()
else:
return Response({
'code': 400,
'content': {
'status': 'FAILED',
'msg': user_data.errors,
}
})
return Response({
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': user_data.validated_data,
}
})
postman测试
1.10 更新一个接口(post)
Serializers.py
from rest_framework import serializers
from . import models
class Userserializers(serializers.Serializer):
# 序列化一个Model类对象就是序列化该类的每一个属性变成字符串给前端使用
name = serializers.CharField()
password = serializers.CharField()
create_time = serializers.DateTimeField()
gender = serializers.SerializerMethodField()
def get_gender(self, obj): # obj 为queryset 对象, 所以可以使用ORM方法操作
return obj.get_sex_display()
class UserDeserializers(serializers.Serializer):
name = serializers.CharField(label="姓名", max_length=32, min_length=3, error_messages={
'max_length': '姓名太长',
'min_length': '姓名太短'
})
password = serializers.CharField(label='密码', max_length=64, min_length=3, error_messages={
'max_length': '密码太长',
'min_length': '密码太短'
})
sex = serializers.IntegerField()
create_time = serializers.DateTimeField(required=False)
# AssertionError: You cannot call `.save()` on a serializer with invalid data.
def create(self, validated_data):
# '`create()` did not return an object instance.'
# AssertionError: `create()` did not return an object instance.
# class BaseSerializer(Field):
# def create(self, validated_data):
# raise NotImplementedError('`create()` must be implemented.')
#
# def save(self, **kwargs):
# assert hasattr(self, '_errors'), (
# 'You must call `.is_valid()` before calling `.save()`.'
# )
#
# assert not self.errors, (
# 'You cannot call `.save()` on a serializer with invalid data.'
# )
#
# # Guard against incorrect use of `serializer.save(commit=False)`
# assert 'commit' not in kwargs, (
# "'commit' is not a valid keyword argument to the 'save()' method. "
# "If you need to access data before committing to the database then "
# "inspect 'serializer.validated_data' instead. "
# "You can also pass additional keyword arguments to 'save()' if you "
# "need to set extra attributes on the saved model instance. "
# "For example: 'serializer.save(owner=request.user)'.'"
# )
#
# assert not hasattr(self, '_data'), (
# "You cannot call `.save()` after accessing `serializer.data`."
# "If you need to access data before committing to the database then "
# "inspect 'serializer.validated_data' instead. "
# )
#
# validated_data = {**self.validated_data, **kwargs}
#
# if self.instance is not None:
# self.instance = self.update(self.instance, validated_data)
# assert self.instance is not None, (
# '`update()` did not return an object instance.'
# )
# else:
# self.instance = self.create(validated_data)
# assert self.instance is not None, (
# '`create()` did not return an object instance.'
# )
#
# return self.instance
print(validated_data)
self.instance = models.User.objects.create(**validated_data)
print(self.instance)
return self.instance
def update(self, instance, validated_data):
print('validated_data', validated_data)
instance.name = validated_data.get('name')
instance.password = validated_data.get('password')
instance.sex = validated_data.get('sex')
return instance
views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import User
from .Serializers import Userserializers, UserDeserializers
class UserView(APIView):
# 获取所有资源
def get(self, request, *args, **kwargs):
user_list = User.objects.all()
print(user_list)
user_data = Userserializers(instance=user_list, many=True).data
return Response({
'code': 200,
'content': {
'msg': 'SUCCESS',
'data': user_data
}
})
# 新增资源
def post(self, request, *args, **kwargs):
# AssertionError: Cannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance.
user_data = UserDeserializers(data=request.data)
# 校验不通过报错信息在前台显示
result = user_data.is_valid(raise_exception=True)
if result:
new_userdataobj = user_data.save()
else:
return Response({
'code': 400,
'content': {
'status': 'FAILED',
'msg': user_data.errors,
}
})
return Response({
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': Userserializers(new_userdataobj).data,
}
})
def put(self, request, *args, **kwargs):
pk = kwargs.get('pk')
old_data = User.objects.get(pk=pk)
print(old_data)
print(request.data)
user_data = UserDeserializers(instance=old_data, data=request.data)
result = user_data.is_valid()
if result:
new_userdataobj = user_data.save()
print('new_userdataobj', new_userdataobj)
else:
return Response({
'code': 400,
'content': {
'status': 'FAILED',
'msg': user_data.errors,
}
})
return Response({
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': Userserializers(new_userdataobj).data,
}
})
1.11 更新一个接口(queryset反序列化)
Serializers.py
from rest_framework import serializers
from . import models
class Userserializers(serializers.Serializer):
# 序列化一个Model类对象就是序列化该类的每一个属性变成字符串给前端使用
name = serializers.CharField()
password = serializers.CharField()
create_time = serializers.DateTimeField()
gender = serializers.SerializerMethodField()
def get_gender(self, obj): # obj 为queryset 对象, 所以可以使用ORM方法操作
return obj.get_sex_display()
class UserDeserializers(serializers.Serializer):
name = serializers.CharField(label="姓名", max_length=32, min_length=3, error_messages={
'max_length': '姓名太长',
'min_length': '姓名太短'
})
password = serializers.CharField(label='密码', max_length=64, min_length=3, error_messages={
'max_length': '密码太长',
'min_length': '密码太短'
})
sex = serializers.IntegerField()
create_time = serializers.DateTimeField(required=False)
# AssertionError: You cannot call `.save()` on a serializer with invalid data.
def create(self, validated_data):
# '`create()` did not return an object instance.'
# AssertionError: `create()` did not return an object instance.
# class BaseSerializer(Field):
# def create(self, validated_data):
# raise NotImplementedError('`create()` must be implemented.')
#
# def save(self, **kwargs):
# assert hasattr(self, '_errors'), (
# 'You must call `.is_valid()` before calling `.save()`.'
# )
#
# assert not self.errors, (
# 'You cannot call `.save()` on a serializer with invalid data.'
# )
#
# # Guard against incorrect use of `serializer.save(commit=False)`
# assert 'commit' not in kwargs, (
# "'commit' is not a valid keyword argument to the 'save()' method. "
# "If you need to access data before committing to the database then "
# "inspect 'serializer.validated_data' instead. "
# "You can also pass additional keyword arguments to 'save()' if you "
# "need to set extra attributes on the saved model instance. "
# "For example: 'serializer.save(owner=request.user)'.'"
# )
#
# assert not hasattr(self, '_data'), (
# "You cannot call `.save()` after accessing `serializer.data`."
# "If you need to access data before committing to the database then "
# "inspect 'serializer.validated_data' instead. "
# )
#
# validated_data = {**self.validated_data, **kwargs}
#
# if self.instance is not None:
# self.instance = self.update(self.instance, validated_data)
# assert self.instance is not None, (
# '`update()` did not return an object instance.'
# )
# else:
# self.instance = self.create(validated_data)
# assert self.instance is not None, (
# '`create()` did not return an object instance.'
# )
#
# return self.instance
print(validated_data)
self.instance = models.User.objects.create(**validated_data)
print(self.instance)
return self.instance
def update(self, instance, validated_data):
print('validated_data', validated_data)
instance.update(**validated_data)
return instance
views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import User
from .Serializers import Userserializers, UserDeserializers
class UserView(APIView):
# 获取所有资源
def get(self, request, *args, **kwargs):
user_list = User.objects.all()
print(user_list)
user_data = Userserializers(instance=user_list, many=True).data
return Response({
'code': 200,
'content': {
'msg': 'SUCCESS',
'data': user_data
}
})
# 新增资源
def post(self, request, *args, **kwargs):
# AssertionError: Cannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance.
user_data = UserDeserializers(data=request.data)
# 校验不通过报错信息在前台显示
result = user_data.is_valid(raise_exception=True)
if result:
new_userdataobj = user_data.save()
else:
return Response({
'code': 400,
'content': {
'status': 'FAILED',
'msg': user_data.errors,
}
})
return Response({
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': Userserializers(new_userdataobj).data,
}
})
def put(self, request, *args, **kwargs):
pk = kwargs.get('pk')
# old_data = User.objects.get(pk=pk)
old_data = User.objects.filter(pk=pk)
user_data = UserDeserializers(instance=old_data, data=request.data)
result = user_data.is_valid()
print('result', result)
if result:
new_userdataobj = user_data.save()
print('new_userdataobj', new_userdataobj.first())
else:
return Response({
'code': 400,
'content': {
'status': 'FAILED',
'msg': user_data.errors,
}
})
return Response({
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': Userserializers(new_userdataobj.first()).data,
}
})
![image-20210117204246052](/Users/chenjiawei/Library/Application Support/typora-user-images/image-20210117204246052.png)
1.12 删除一个接口
1.12.1 添加数据库字段 is_delete
- 更新
model.py
, 添加is_delete
字段
from django.db import models
class User(models.Model):
CHOICE_SEX = (
(0, '男'),
(1, '女')
)
name = models.CharField(max_length=32, verbose_name='姓名')
password = models.CharField(max_length=64, verbose_name='密码')
sex = models.SmallIntegerField(choices=CHOICE_SEX, default=0)
create_time = models.DateTimeField(auto_now_add=True, blank=True)
is_delete = models.BooleanField(default=False)
class Meta:
db_table = 'o_user' # 自定义创建的表名
verbose_name = '用户' # admin/xadmin 界面中显示的表名
verbose_name_plural = verbose_name # admin/xadmin 界面中显示的表名复数形式
def __str__(self):
return self.name
- 生成数据库脚本文件
python3 manage.py makemigrations
- 执行数据库脚本文件
python3 manage.py migrate
1.12.2. 写接口
Serializers.py
无需修改
- 写接口
views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import User
from .Serializers import Userserializers, UserDeserializers
class UserView(APIView):
# 获取所有资源
def get(self, request, *args, **kwargs):
user_list = User.objects.filter(is_delete=False).all()
print(user_list)
user_data = Userserializers(instance=user_list, many=True).data
return Response({
'code': 200,
'content': {
'msg': 'SUCCESS',
'data': user_data
}
})
# 新增资源
def post(self, request, *args, **kwargs):
# AssertionError: Cannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance.
user_data = UserDeserializers(data=request.data)
# 校验不通过报错信息在前台显示
result = user_data.is_valid(raise_exception=True)
if result:
new_userdataobj = user_data.save()
else:
return Response({
'code': 400,
'content': {
'status': 'FAILED',
'msg': user_data.errors,
}
})
return Response({
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': Userserializers(new_userdataobj).data,
}
})
def put(self, request, *args, **kwargs):
pk = kwargs.get('pk')
# old_data = User.objects.get(pk=pk)
old_data = User.objects.filter(pk=pk)
user_data = UserDeserializers(instance=old_data, data=request.data)
result = user_data.is_valid()
print('result', result)
if result:
new_userdataobj = user_data.save()
print('new_userdataobj', new_userdataobj.first())
else:
return Response({
'code': 400,
'content': {
'status': 'FAILED',
'msg': user_data.errors,
}
})
return Response({
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': Userserializers(new_userdataobj.first()).data,
}
})
def delete(self, request, *args, **kwargs):
pk = kwargs.get('pk')
try:
data_obj = User.objects.get(pk=pk)
data_obj.is_delete = True
data_obj.save()
response = {
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': f'{data_obj}删除成功',
}
}
except Exception as e:
response = {
'code': 400,
'content': {
'status': 'FAILED',
'msg': e,
}
}
return Response(response)
1.13 获得一条数据
Serializers.py
无需修改
views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import User
from .Serializers import Userserializers, UserDeserializers
class UserView(APIView):
# 获取所有资源
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk', None)
if not pk:
user_list = User.objects.filter(is_delete=False).all()
else:
user_list = User.objects.filter(is_delete=False, pk=pk)
print(user_list)
user_data = Userserializers(instance=user_list, many=True).data
return Response({
'code': 200,
'content': {
'msg': 'SUCCESS',
'data': user_data
}
})
# 新增资源
def post(self, request, *args, **kwargs):
# AssertionError: Cannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance.
user_data = UserDeserializers(data=request.data)
# 校验不通过报错信息在前台显示
result = user_data.is_valid(raise_exception=True)
if result:
new_userdataobj = user_data.save()
else:
return Response({
'code': 400,
'content': {
'status': 'FAILED',
'msg': user_data.errors,
}
})
return Response({
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': Userserializers(new_userdataobj).data,
}
})
def put(self, request, *args, **kwargs):
pk = kwargs.get('pk')
# old_data = User.objects.get(pk=pk)
old_data = User.objects.filter(pk=pk)
user_data = UserDeserializers(instance=old_data, data=request.data)
result = user_data.is_valid()
print('result', result)
if result:
new_userdataobj = user_data.save()
print('new_userdataobj', new_userdataobj.first())
else:
return Response({
'code': 400,
'content': {
'status': 'FAILED',
'msg': user_data.errors,
}
})
return Response({
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': Userserializers(new_userdataobj.first()).data,
}
})
def delete(self, request, *args, **kwargs):
pk = kwargs.get('pk')
try:
data_obj = User.objects.get(pk=pk)
data_obj.is_delete = True
data_obj.save()
response = {
'code': 200,
'content': {
'status': 'SUCCESS',
'msg': f'{data_obj}删除成功',
}
}
except Exception as e:
response = {
'code': 400,
'content': {
'status': 'FAILED',
'msg': e,
}
}
return Response(response)