Django 基本使用
前后端分离开发模式
1.1 前后端分离前
1.2 前后端分离前存在的一些问题
• PC、APP、Pad等多端流行 • 前后端开发职责不清晰:各司其职,最大程度减少开发难度,方便协作 • 开发效率问题,一般后端开发需先等前端页面准备好,有时前端也一直配 合后端,能力受限 • 前后端代码混在一起,日积月累,维护成本增加 • 后端开发语言和模板耦合
1.3 前后端分离开发模式
RestFulAPI
1.1 什么是RestfulAPI: • REST(Representational State Transfer,表征状态转移)是一种Web服务的软件架构风格。 描述网络中客户端与服务端的一种交互方式,它本身不常用,常用的是如何设计RestfulAPI (REST风格的网络接口) • RestfulAPI风格就是把所有的数据都当做资源,对表的操作就是对资源操作 • 资源就是指的URL,基于URL对资源操作,Web服务在URL上支持一系列请求方法,如下表所 示。
Django开发模式
1.1 Django工作流程
1.2 django案列创建一个用户信心管理实现增删改查
1.3.1 首先使用Pycharm创建一个新项目
1.3.2 创建应用myapp
python manage.py startapp myapp
1.3.3 myapp/models.py编写数据模型
from django.db import models
# Create your models here.
class User(models.Model):
name = models.CharField(max_length=30)
city = models.CharField(max_length=30)
sex = models.CharField(max_length=30)
age = models.IntegerField()
1.3.4 user_info项目重的settings.py中注册myapp
1.3.5 user_info 路由urls.py中定义myapp的路由
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('myapp/', include('myapp.urls'))
]
1.3.6 同步数据库
python manage.py makemigrations python manage.py migrate
1.3.7 定义应用myapp路由urls.py
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
# path('user/', views.user),
path('user/', views.UserView.as_view()),
path('user_add', views.user_add),
path('user_edit', views.user_edit)
]
1.3.8 定义myapp试图views.py
from django.shortcuts import render
from django.http import HttpResponse, QueryDict, JsonResponse
from .models import User
from django.views.generic import View
def user_add(request):
return render(request, 'user_add.html')
def user_edit(request):
id = request.GET.get('id')
user_obj = User.objects.get(id=id)
return render(request, 'user_edit.html', {'id': id, 'user': user_obj})
# def user(request):
# if request.method == "GET":
# if request.GET.get('id'):
# pass
# # user_obj = User.objects.get(id=request.GET.get('id'))
# # res = {'code': 200, 'msg': '成功!', user_obj: user_obj}
# # return JsonResponse(res)
# else:
# user_list = User.objects.all()
# return render(request, 'user_list.html', {'user_list': user_list})
# elif request.method == "POST":
# name = request.POST.get('name')
# city = request.POST.get('city')
# sex = request.POST.get('sex')
# age = request.POST.get('age')
# User.objects.create(
# name=name,
# city=city,
# sex=sex,
# age=age
# )
# return HttpResponse("创建用户成功!")
# elif request.method == "PUT":
# data = QueryDict(request.body)
# id = data.get('id')
# user_obj = User.objects.get(id=id)
# user_obj.city = data.get('city')
# user_obj.sex = data.get('sex')
# user_obj.age = data.get('age')
# user_obj.save()
# # 方式2
# # data = {'city': data.get('city'), 'sex': data.get('sex'), 'age': data.get('age')}
# # User.objects.filter(id=id).update(**data)
# res = {'code': 200, 'msg': '更新成功!'}
# return JsonResponse(res)
# elif request.method == "DELETE":
# data = QueryDict(request.body)
# id = data.get('id')
# try:
# User.objects.get(id=id).delete()
# res = {'code': 200, 'msg': '删除用户成功!'}
# except Exception:
# res = {'code': 500, 'msg': '删除用户失败!'}
#
# return JsonResponse(res)
class UserView(View):
def get(self, request):
if request.GET.get('id'):
pass
# user_obj = User.objects.get(id=request.GET.get('id'))
# res = {'code': 200, 'msg': '成功!', user_obj: user_obj}
# return JsonResponse(res)
else:
user_list = User.objects.all()
return render(request, 'user_list.html', {'user_list': user_list})
def post(self, request):
name = request.POST.get('name')
city = request.POST.get('city')
sex = request.POST.get('sex')
age = request.POST.get('age')
User.objects.create(
name=name,
city=city,
sex=sex,
age=age
)
return HttpResponse("创建用户成功!")
def put(self, request):
data = QueryDict(request.body)
id = data.get('id')
user_obj = User.objects.get(id=id)
user_obj.city = data.get('city')
user_obj.sex = data.get('sex')
user_obj.age = data.get('age')
user_obj.save()
# 方式2
# data = {'city': data.get('city'), 'sex': data.get('sex'), 'age': data.get('age')}
# User.objects.filter(id=id).update(**data)
res = {'code': 200, 'msg': '更新成功!'}
return JsonResponse(res)
def delete(self, request):
data = QueryDict(request.body)
id = data.get('id')
try:
User.objects.get(id=id).delete()
res = {'code': 200, 'msg': '删除用户成功!'}
except Exception:
res = {'code': 500, 'msg': '删除用户失败!'}
return JsonResponse(res)
1.3.9 创建添加、编辑、获取用户信息前端html
添加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>创建用户</title>
</head>
<body>
<form action="">
姓名: <input type="text" name="name"><br>
城市: <input type="text" name="city"><br>
姓名: <input type="text" name="sex"><br>
年龄: <input type="text" name="age"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
获取
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>列出所有用户</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body>
<button><a href="/myapp/user_add" target="_blank">创建用户</a></button>
<table border="1">
<thead>
<tr>
<th style="display: none">ID</th>
<th>姓名</th>
<th>城市</th>
<th>性别</th>
<th>年龄</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for i in user_list %}
<tr>
<td style="display: none">{{ i.id }}</td>
<td>{{ i.name }}</td>
<td>{{ i.city }}</td>
<td>{{ i.sex }}</td>
<td>{{ i.age }}</td>
<td>
<button><a href="/myapp/user_edit?id={{ i.id }}" target="_blank">编辑</a></button>
<button id="del" onclick="delUser(this)">删除</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
function delUser(obj) {
confirm = confirm('是否删除该用户?');
if (confirm) {
id = $(obj).parent().parent().find("td:eq(0)").text(); // 获取button父元素td,再获取td父元素tr,最后获取tr第一个td值
data = {'id': id};
$.ajax({
type: 'DELETE',
url: '/myapp/user/',
data: data,
success: function (result) {
if(result.code === 200) {
alert(result.msg);
location.reload();
} else {
alert(result.msg)
}
}
})
}
}
</script>
</body>
</html>
1.3.10 编辑
<head>
<meta charset="UTF-8">
<title>编辑用户</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body>
<h2>编辑用户</h2>
<form action="#">
<input type="text" name="id" value="{{ user.id }}" style="display: none">
姓名:<input type="text" name="name" value="{{ user.name }}"><br>
城市:<input type="text" name="city" value="{{ user.city }}"><br>
性别:<input type="text" name="sex" value="{{ user.sex }}"><br>
年龄:<input type="text" name="age" value="{{ user.age }}"><br>
<input type="button" value="提交" onclick="go()">
</form>
<script>
function go() {
id = $('input[name=id]').val();
name = $('input[name=name]').val();
city = $('input[name=city]').val();
sex = $('input[name=sex]').val();
age = $('input[name=age]').val();
data = {'id': id, 'name': name, 'city': city, 'sex': sex, 'age': age};
$.ajax({
type: 'PUT',
url: '/myapp/user/',
data: data,
success: function (result) {
if ( result.code === 200 ) {
alert(result.msg)
}
}
})
}
</script>
</body>
</html>
1.3.11 启动myapp应用
Django REST Framework初探
DRF 实现用户增删改查
1 安装Django REST Framework
pip install djangorestframework
2 添加rest_framework到INSRTALLED_APPS设置中
3创建app
python manage.py startapp myapp_api
4 定义数据模型并同步数据库
from django.db import models
# Create your models here.
class User(models.Model):
name = models.CharField(max_length=30)
city = models.CharField(max_length=30)
sex = models.CharField(max_length=30)
age = models.IntegerField()
python manage.py makemigrations python manage.py migrate
5 编写序列化器文件myapp_api/serializers.py
from myapp.models import User
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User #指定数据类型
fields = "__all__" #显示所有字段
6 定义视图
from rest_framework import viewsets
from .serializers import UserSerializer
from myapp.models import User
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all() #指定操作的数据
serializer_class = UserSerializer #指定序列化器
7 添加API路由devops/urls.py和应用myapp/urls.py
from django.contrib import admin
from django.urls import path ,include,re.path
urlpatterns = [
path('admin/', admin.site.urls),
re_path('myapp/',include('myapp.urls')),
re_path('api/',include('myapp_api.urls')),
]
from django.urls import path,re_path,include
from myapp_api import views
from rest_framework import routers
#自动注册路由
router = routers.DefaultRouter()
router.register(r'user',views.UserViewSet)
urlpatterns = [
path('api',include(router.urls))
]
8 调用地址完成增删改查
Django DRF序列化器
什么是序列化?
序列化 (Serialization),是指把程序中的一个类转化成一个标准化的格式。标准化的意义是这个格式可以跨程序,跨平台的被使用,而且保持其原有的内容,规范。
为什么要对数据进行序列化?
一致性:我们将要保存的数据,序列化成标准的格式(Json格式或者Pickle格式)。之后再反序列化回来,数据依然是原来的。保持了数据的一致性。
有效性: 序列化之后,可以减少内存和网络资源的占用
兼容性: 使用python进行了数据的序列化,也可以使用java或者其他语言进行反序列得到数据进行使用。
什么是序列化?什么是反序列化?
序列化:将python对象转json
反序列化: 将python对象转json
序列化器的工作流程:
序列化(读数据):视图通过ORM从数据库获取数据库查询集对象->数据传入序列化器->
序列化器对数据进行序列化->调用序列化器的.data获取数据->响应返回给前端
反序列化(写数据):试图获取前端提交数据-> 数据传入序列化器->调用序列化器的.is_valid方法效验数据->调用序列化器的.save()方法保存数据
序列化器常用方法与属性:
serializer.is_vaild():调用序列化器验证数据,传入raise_exception=True可以在验证失败时由DRF响应400异常
serializer.errors: 获取反序列化器验证的错误信息
serializer.data:获取序列化器返回的数据
serializer.save(): 将验证通过的数据保存到数据库(ORM操作)
DRF中序列化器支持的三种类型:
Serializer:对Model(数据模型)进行序列化,但是需要自定义字段映射
ModelSerializer:对Model进行序列化,会自动生成字段和验证规则,默认还包含简单的create()和update()方法
HyperlinkedModelSerializer: 与ModelSerializer类似,只不过使用超链接来表示关系而不是主键id
DRF序列化器使用
Serializer序列化器
1、获取所有用户(查)
1.1 定义序列化器 myapp_api/serializers.py
class UserSerializer(serializers.Serializer):
#序列化器中定义的字段必须与使用模型字段对应
id = serializers.IntegerField()
name = serializers.CharField(max_length=30)
city = serializers.CharField(max_length=30)
sex = serializers.CharField(max_length=30)
age = serializers.IntegerField()
1.2 视图中使用定义好的序列化器 myapp_api/views.py
from rest_framework.views import APIView
from .serializers import UserSerializer
from myapp.models import User
from rest_framework.response import Response
# class UserViewSet(viewsets.ModelViewSet):
# queryset = User.objects.all() #指定操作的数据
# serializer_class = UserSerializer #指定序列化器
class UserView(APIView):
def get(self,request):
# 获取所有用户
queryset = User.objects.all()
# 调用序列化器将queryset对象转为json
user_ser = UserSerializer(queryset,many=True) #如果序列化多条数据,需要指定many=True
return Response(user_ser.data) #从.data属性中获取序列化结果
1.3定义路由myapp_api/urls.py
from django.urls import path,re_path,include
from myapp_api import views
urlpatterns = [
path('^api/user/$',views.UserView.as_view()),
]
2、获取单个用户
2.1 定义获取单个用户视图
from rest_framework.views import APIView
from .serializers import UserSerializer
from myapp.models import User
from rest_framework.response import Response
class UserView(APIView):
def get(self,request,pk=None):
if pk:
# 获取单个用户
user_obj = User.objects.get(id=pk)
user_ser = UserSerializer(user_obj)#调用序列化器将获取的单个用户数据对象转换为json
else:
# 获取所有用户
queryset = User.objects.all()
# 调用序列化器将queryset对象转为json
user_ser = UserSerializer(queryset,many=True) #如果序列化多条数据,需要指定many=True
result = {'code':200,'msg': "获取用户成功",'data': user_ser.data}
return Response(result) #从.data属性中获取序列化结果
2.2 定义路由myapp_api/urls.py
from django.urls import path,re_path,include
from myapp_api import views
urlpatterns = [
re_path('^api/user/$',views.UserView.as_view()),
re_path('^api/user/(?P<id>\d)/$',views.UserView.as_view()),
]
2.3 获取单个用户测试
3 创建用户
3.1 定义视图myapp_api/views.py 增加post方法接收数据
def post(self,request):
#调用序列化器将提交的数据进行反序列化
user_ser = UserSerializer(data=request.data)
# 判断提交的数据反序列化是否通过验证
if user_ser.is_valid():
# 判断通过则保存到数据库
user_ser.save()
msg = '创建用户成功'
code = 200
else:
msg = '提交数据格式不对!创建用户失败'
code = 400
result = {'code': code,'msg': msg}
return Response(result)
3.2 myapp_api/serializers.py定义create()方法
class UserSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=30)
city = serializers.CharField(max_length=30)
sex = serializers.CharField(max_length=30)
age = serializers.IntegerField()
def create(self, validated_data): # 定义create方法validated_data是提交的json数据
return User.objects.create(**validated_data)
3.3 测试创建用户
4、定义更新用户
4.1 定义视图: 增加myapp_api/views.py PUT方法接收数据
def put(self,request,id=None):
# 获取需要更新数据的用户,将用户默认pk赋值给id
user_obj = User.objects.get(id=id)
# 调用序列化器,传入已有的对象和提交数据
user_ser = UserSerializer(instance=user_obj,data=request.data)
if user_ser.is_valid():
user_ser.save()
msg = '更新用户成功'
code = 200
else:
msg = '更新用户失败,数据格式不正确!'
code = 400
result = {'code': code, 'msg': msg}
return Response(result)
4.2 myapp_api/serializers.py中增加update()方法
def update(self, instance, validated_data):
return User.objects.filter(id=instance.id).update(**validated_data)
4.3 测试更新用户
5 、删除用户
5.1 定义删除单个用户视图myapp_api/views.py
def delete(self,request,id=None):
user_obj = User.objects.get(id=id)
try:
user_obj.delete()
result = {'code': 200, 'msg': '用户删除成功'}
except Exception as e:
result = {'code': 500, 'mgs': '用户删除失败'}
return Response(result)
ModelSerializer 序列化器
ModelSerializer 类型不需要自定义字段映射和定义create、update方法,使用起来方便很多! 如下使用ModelSerializer只需要定义视图、序列化器和自动注册路由
1 定义序列化器 myapp_api/serializers.py
class UserSerializer(serializers.ModelSerializer): #定义序列化器类,并继承serializers.ModelSerializer
class Meta:
model = User #指定数据类型
fields = '__all__' #显示所有字段
2 定义视图myapp_api/views.py
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all() #指定操作的数据
serializer_class = UserSerializer #指定序列化器
3 定义自动注册路由
from django.urls import path,re_path,include
from myapp_api import views
from rest_framework import routers
#自动注册路由
router = routers.DefaultRouter()
router.register(r'user',views.UserViewSet)
urlpatterns = [
path('api',include(router.urls))
]
HyperModelSerializer 序列化器
与MedelSerializer使用方法一样。只不过它使用超链接来表示关系而不是主键ID。
# 更改序列化器
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = "__all__“
# 更改视图
user_ser = UserSerializer(queryset, many=True, context={'request': request})
# 更改路由
re_path('^api/user/$', views.UserView.as_view(), name="user-detail"),
re_path('^api/user/(?P<pk>\d+)/$', views.UserView.as_view(), name="user-detail"),
序列化器常用参数
1、 在myapp_api/serializers.py中设置序列花器参数
class UserSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True) #当设置为True时该字段提交默认忽略
name = serializers.CharField(max_length=30,
error_messages={ # 设置错误提示
"blank": "请输入姓名",
"required": "该字段必填",
"max_lenth": "字符长度不超过30",
})
city = serializers.CharField(max_length=10,
error_messages={ # 设置错误提示
"blank": "请输入城市",
"required": "该字段必填",
"max_lenth": "字符长度不超过10",
})
sex = serializers.CharField(max_length=10,
error_messages={ # 设置错误提示
"blank": "请输入性别",
"required": "该字段必填",
"max_lenth": "字符长度不超10",
})
age = serializers.IntegerField(min_value=18,max_value=100,
error_messages={ # 设置错误提示
"blank": "请输入年龄",
"required": "该字段必填",
"min_value": "年龄不低于18",
"max_value": "年龄不超过100岁",
})
2 、views.py视图修改方法中数据.is_valid(raise_exception=True),下面我只修改了post方法,其他方法修改也是一样的
def post(self,request):
#调用序列化器将提交的数据进行反序列化
user_ser = UserSerializer(data=request.data)
user_ser.is_valid(raise_exception=True)
result = {'code': 200,'msg': '创建用户成功'}
return Response(result)
3、测试post提交数据缺少age字段
序列器扩展验证规则
当常用参数无法满足验证要求时可以通过钩子方法扩展验证规则
局部钩子:validate_字段名(self, 字段值)
serializers.py中定义局部钩子
# 局部钩子: 针对某个字段验证合法性
def validate_name(self,attrs): #attrs是该字段的值
from re import findall
if findall('\d+',attrs):
raise serializers.ValidationError("姓名中不能包含数字!")
else:
return attrs
全局钩子:validate_字段名(self, 字段值)
# 全局钩子:针对所有字段验证
def validate(self,attrs): #attrs是所有字段组成的字典
sex = attrs.get('sex')
if sex != "男" and sex != "女":
raise serializers.ValidationError("性别只能是男/女!")
else:
return attrs
3 如果钩子也无法满足需求可以,自定义验证器。在序列化类外面定义验证器,使用validators参数指定验证器。
def check_name(data):
if data.startswith("x"):
raise serializers.ValidationError("姓名不能以x开头")
else:
return data
class UserSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True) #当设置为True时该字段提交默认忽略
name = serializers.CharField(max_length=30,validators=[check_name],
error_messages={ # 设置错误提示
"blank": "请输入姓名",
"required": "该字段必填",
"max_lenth": "字符长度不超过30",
})
序列化器关联表显示
如应用发布系统项目涉及表
一对多:一个项目有多个应用,一个应用只能属于一个项目
多对多:一台应用可以部署到多台服务器,一个服务器也能部署多个应用
创建新应用Association_table
python manager.py startapp Association_table
定义数据模型,模型定义好了需要同步数据库
python manager.py makemigrations
python manager.py migrate
from django.db import models
class Project(models.Model):
name = models.CharField(max_length=30)
class App(models.Model):
name = models.CharField(max_length=30)
project = models.ForeignKey(Project,on_delete=models.CASCADE) #一对多
class Server(models.Model):
hostname = models.CharField(max_length=30)
ip = models.GenericIPAddressField()
app = models.ManyToManyField(App) #多对多
定义序列化器
from rest_framework import serializers
from Association_table.models import Project,App,Server
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = "__all__"
class AppSerializer(serializers.ModelSerializer):
class Meta:
model = App
fields = "__all__"
class ServerSerializer(serializers.ModelSerializer):
class Meta:
model = Server
fields = "__all__"
定义视图
from rest_framework.views import APIView
from Association_table.models import Project,App,Server
from .serializers import ProjectSerializer,AppSerializer,ServerSerializer
from rest_framework.response import Response
# Create your views here.
class ProjectView(APIView):
def get(self, request, id=None):
if id:
obj = Project.objects.get(id=id)
ser = ProjectSerializer(obj)
else:
queryset = Project.objects.all()
ser = ProjectSerializer(queryset, many=True)
res = {'code': 200, 'msg': '获取成功!', 'data': ser.data}
return Response(res)
def post(self, request):
ser = ProjectSerializer(data=request.data)
ser.is_valid(raise_exception=True)
ser.save()
res = {'code': 200, 'msg': '创建用户成功!'}
return Response(res)
class AppView(APIView):
def get(self, request, id=None):
if id:
obj = App.objects.get(id=id)
ser = AppSerializer(obj)
else:
queryset = App.objects.all()
ser = AppSerializer(queryset, many=True)
res = {'code': 200, 'msg': '获取成功!', 'data': ser.data}
return Response(res)
def post(self, request):
ser = AppSerializer(data=request.data)
ser.is_valid(raise_exception=True)
ser.save()
res = {'code': 200, 'msg': '创建用户成功!'}
return Response(res)
class ServerView(APIView):
def get(self, request, id=None):
if id:
obj = Server.objects.get(id=id)
ser = ServerSerializer(obj)
else:
queryset = Server.objects.all()
ser = ServerSerializer(queryset, many=True)
res = {'code': 200, 'msg': '获取成功!', 'data': ser.data}
return Response(res)
def post(self, request):
ser = ServerSerializer(data=request.data)
ser.is_valid(raise_exception=True)
ser.save()
res = {'code': 200, 'msg': '创建用户成功!'}
return Response(res)
定义路由
from django.urls import re_path
from . import views
urlpatterns = [
re_path('^api/project/$', views.ProjectView.as_view()),
re_path('^api/app/$', views.AppView.as_view()),
re_path('^api/server/$', views.ServerView.as_view()),
]
添加测试数据
创建项目:
from Association_table.models import Project, App, Server
Project.objects.create(name="电商")
Project.objects.create(name="教育")
创建应用并指定项目:
project_obj = Project.objects.get(name="电商")
App.objects.create(name="portal", project=project_obj)
App.objects.create(name="gateway", project=project_obj)
创建服务器:
Server.objects.create(hostname="test1", ip="192.168.31.10")
Server.objects.create(hostname="test2", ip="192.168.31.11")
将应用部署到服务器:
app_obj = App.objects.get(name="portal")
server_obj = Server.objects.get(hostname="test1")
server_obj.app.add(app_obj)
7 序列化器返回是当前模型中的字段,如果字段是外键时,返回的是外键对应的id,如下图所示
对于这种情况有两种方法可以显示外键对应的详细信息
定义字段为外键对应序列化类:例如project=ProjectSerializer(read_only=Ture),该方法适合针对某个外键字段。
class AppSerializer(serializers.ModelSerializer):
project = ProjectSerializer(read_only=True) # 一对多,返回关联的项目详情
class Meta:
model = App
fields = "__all__"
序列化类中Meta类启用dpth:深度获取关联表数据,这种对所有外键都会显示
class AppSerializer(serializers.ModelSerializer):
class Meta:
model = App
fields = "__all__"
depth = 1
修改后如下图就可以显示外键对应的详细值
SerializerMethodField
SerializerMethodField可以在不修改数据模型的前提下,增加API字段
DRF序列器默认返回数据模型中已存在资源,如果想新增返回字段或者二次处理,则需要用用到SerializerMethodFiled
#实例给项目API增加一个字段,这个字段数据可以从别的表中获取
class ProjectSerializer(serializers.ModelSerializer):
app_acount = serializers.SerializerMethodField()
class Meta:
model = Project
fields = "__all__"
def get_app_acount(self,obj):
return len(obj.app_set.all())
序列化和反序列化的行为:
to_internal_value():处理反序列化的输入数据,自动转换Python对象,方便处理
to_representation():处理序列化数据的输出。
什么时候需要用到反序列化的行为?
当提交API数据与序列化器要求的格式不符合时,序列化就会抛出错误,这个时候就可以使用to_internal_value()方法来提取符合序列化器要求的数据格式
例如:前端提交一个创建新项目的数据
{
"data": {
"id": 3,
"name": "大数据"
},
"extra_data":{
"count": 123
}
}
如下在序列化器中将符合序列化器的data数据使用to_internal_value方法重写后,就可以正常创建了
class ProjectSerializer(serializers.ModelSerializer):
app_acount = serializers.SerializerMethodField()
class Meta:
model = Project
fields = "__all__"
def get_app_acount(self,obj):
return len(obj.app_set.all())
def to_internal_value(self, data):
# data是前端提交未验证的数据
data = data['data']
return super().to_internal_value(data)
什么时候用到序列化行为?
当需要给返回的数据添加一个统计应用数量的字段时
class ProjectSerializer(serializers.ModelSerializer):
#app_acount = serializers.SerializerMethodField()
class Meta:
model = Project
fields = "__all__"
# def get_app_acount(self,obj):
# return len(obj.app_set.all())
def to_representation(self, instance):
data = super().to_representation(instance) #获取预返回前的数据
data['app_acount'] = len(instance.app_set.all())
return data