1. 简介
- 在Django框架基础上进行二次开发,用于构建Restful API,简称DRF
- 强大的Serializer序列化器,可以高效的进行序列化和反序列化操作;
- 极为丰富的类视图、Mixin扩展类、ViewSet视图集;
- 提供直观的WEB API界面;
- 多种身份认证和权限认证;
- 强大的排序、过滤、分页、搜索、限流等功能;
- 可扩展性,插件丰富
2. 安装配置
pip install djangorestframework
INSTALLED_APPS = [
'rest_framework'
]
3. 序列化器(serializer)
3.1 序列化器
序列化
:将Django模型数据转化为json格式字符串(前段可接收的数据),为序列化反序列化
:前段传过来的json格式数据,转化为Django模型类对象,为反序列化序列化器
:具有序列化和反序列化的功能
3.2 代码
from django.db import models
class Projects(models.Model):
id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')
name = models.CharField(verbose_name='项目名称', max_length=64, unique=True, help_text='项目名称')
leader = models.CharField(verbose_name='项目负责人', max_length=32, help_text='项目负责人')
developer = models.CharField(verbose_name='开发人员', max_length=32, help_text='开发人员')
tester = models.CharField(verbose_name='测试人员', max_length=32, help_text='测试人员')
app_name = models.CharField(verbose_name='应用名称', max_length=32, help_text='应用名称')
desc = models.CharField(verbose_name='简要描述', max_length=256, null=True, blank=True, default='', help_text='简要描述')
class Meta:
"""
表名
"""
db_table = 'tb_projects'
verbose_name = '项目信息'
verbose_name_plural = verbose_name
ordering = ['id']
def __str__(self):
"""
修改admin后台展示的项目名称
"""
return self.name
- 继承(serializers.Serializer)时, 需要重写 update 与 create 方法,因为Serializer 继承 BaseSerializer类,其中update 与 create 方法会直接raise
- serializer.save()时会根据instance 有无,无则调用create,有则调用update,instance可认为是符合序列化结构的数据
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from projects.models import Projects
def is_unique_project_name(name):
if '项目' not in name:
raise serializers.ValidationError('项目名称中必须包含"项目"')
class ProjectsSerializers(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='项目名称', max_length=64, min_length=4, help_text='项目名称',
validators=[UniqueValidator(queryset=Projects.objects.all(), message='项目名称不能重复'),
is_unique_project_name],
error_messages={'max_length': '项目名称不能超过64个字节', 'min_length': '项目名称不能少于4个字节'})
leader = serializers.CharField(label='项目负责人', max_length=32, help_text='项目负责人', write_only=True)
developer = serializers.CharField(label='开发人员', max_length=32, help_text='开发人员')
tester = serializers.CharField(label='测试人员', max_length=32, help_text='测试人员')
app_name = serializers.CharField(label='应用名称', max_length=32, help_text='应用名称')
desc = serializers.CharField(label='项目概述', max_length=256, help_text='项目概述', allow_null=True, allow_blank=True,
default='')
def validate__name(self, value):
if not value.endswith('项目'):
raise serializers.ValidationError('项目名称必须以"项目"结尾')
return value
def validate(self, attrs):
"""
多字段校验器
"""
if '张三' not in attrs['developer'] and '张三' not in attrs['tester']:
raise serializers.ValidationError('"张三"必须是项目开发人员或测试人员')
return attrs
def create(self, validated_data):
return Projects.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.name = validated_data['name']
instance.leader = validated_data['leader']
instance.developer = validated_data['developer']
instance.tester = validated_data['tester']
instance.app_name = validated_data['app_name']
instance.desc = validated_data['desc']
instance.save()
return instance
from django.http import JsonResponse, Http404
from django.views import View
from projects.models import Projects
from projects.serializers import ProjectsSerializers
import json
class ProjectList(View):
""""
类视图
"""
def get(self, request):
projects= Projects.objects.all()
serializer = ProjectsSerializers(instance=projects, many=True)
return JsonResponse(serializer.data, safe=False, status=200)
def post(self, request):
"""
httpie模拟请求:http POST :8000/projects/ name='项目009' leader="zz" developer='李四' tester='张三' \
app_name='测试应用' desc='demo desc'
"""
data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
serializer = ProjectsSerializers(data=data)
try:
serializer.is_valid(raise_exception=True)
except Exception as e:
return JsonResponse(serializer.errors)
serializer.save()
return JsonResponse(serializer.data, safe=False, status=201)
class ProjectDetail(View):
def get_object(self, pk):
"""
根据id判断项目是否存在,存在则返回,不存在则返回404
"""
try:
return Projects.objects.get(id=pk)
except Projects.DoesNotExist:
raise Http404
def get(self, request, pk):
"""
httpie模拟请求:http :8000/projects/12
"""
project = self.get_object(pk)
serializer = ProjectsSerializers(instance=project)
return JsonResponse(serializer.data, safe=False)
def put(self, request, pk):
"""
httpie模拟请求:http PUT :8000/projects/12 name='项目0091' leader="张三" developer='李四' \
tester='王五' app_name='测试应用' app_version='1.0' desc='demo desc'
"""
project = self.get_object(pk)
data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
serializer = ProjectsSerializers(instance=project, data=data)
try:
serializer.is_valid(raise_exception=True)
except Exception as e:
return JsonResponse(serializer.errors)
serializer.save()
return JsonResponse(serializer.data, safe=False, status=201)
def delete(self, request, pk):
"""
httpie模拟请求:http DELETE :8000/projects/12
"""
project = self.get_object(pk)
project.delete()
return JsonResponse(None, safe=False, status=204)
from django.urls import path
from projects import views
urlpatterns = [
path(r'projects/<int:pk>', views.ProjectDetail.as_view()),
path(r'projects/', views.ProjectList.as_view()),
]
4. 模型序列化器(ModelSerializer)
4.1 模型序列化器
- 功能同序列化器,但简化了序列化器的定义
- 基于模型类生成一系列字段
- 基于模型类自动为serializer生成validators,比如unique_together
- 包含默认的create()和update()功能的实现
- PrimaryKeyRelatedField
- StringRelatedField
- SlugRelatedField
4.2 代码
from django.db import models
class Projects(models.Model):
name = models.CharField(verbose_name='项目名称', max_length=64, help_text='项目名称', unique=True)
leader = models.CharField(verbose_name='项目负责人', max_length=32, help_text='项目负责人')
developer = models.CharField(verbose_name='开发人员', max_length=32, help_text='开发人员')
tester = models.CharField(verbose_name='测试人员', max_length=32, help_text='测试人员')
app_name = models.CharField(verbose_name='应用名称', max_length=32, help_text='应用名称')
app_version = models.CharField(verbose_name='应用版本', max_length=32, help_text='应用版本')
desc = models.TextField(verbose_name='项目概述', max_length=256, help_text='项目概述', blank=True, default='', null=True)
class Meta:
"""
表名
"""
db_table = 'tb_projects'
verbose_name = '项目'
verbose_name_plural = '项目'
def __str__(self):
"""
修改admin后台展示的项目名称
"""
return self.name
from django.db import models
class Interfaces(models.Model):
id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')
name = models.CharField(verbose_name='接口名称', max_length=64, unique=True, help_text='接口名称')
tester = models.CharField(verbose_name='测试人员', max_length=32, help_text='测试人员')
desc = models.TextField(verbose_name='接口描述', max_length=256, help_text='接口概述', blank=True, default='', null=True)
project = models.ForeignKey('projects.Projects', on_delete=models.CASCADE, related_name='interfaces', verbose_name='所属项目', help_text='所属项目')
class Meta:
db_table = 'tb_interfaces'
verbose_name = '接口'
verbose_name_plural = '接口'
def __str__(self):
return self.name
- 继承(serializers.ModelSerializer)时,ModelSerializer已重写 update 与 create 方法,没有新的字段时不需要重写这2个方法
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from projects.models import Projects
def is_unique_project_name(name):
if '项目' not in name:
raise serializers.ValidationError('项目名称中必须包含"项目"')
class ProjectModelSerializer(serializers.ModelSerializer):
""""""
name = serializers.CharField(label='项目名称', max_length=64, help_text='项目名称',
validators=[
UniqueValidator(queryset=Projects.objects.all(), message='项目名称不能重复'),
is_unique_project_name])
interfaces = serializers.StringRelatedField(label='拥有的所有接口名称', many=True)
class Meta:
model = Projects
exclude = ('desc', 'app_version')
read_only_fields = ('id', 'desc')
extra_kwargs = {
'name': {
'label': '项目名称',
'max_length': 64,
'min_length': 4,
'write_only': False,
'error_message': {'max_length': '最大长度不超过50字节'},
'validators': [UniqueValidator(queryset=Projects.objects.all(), message='项目名称不能重复'),
is_unique_project_name]
},
'leader': {
'label': '项目负责人',
}
}
def validate_name(self, value):
if not value.endswith('项目'):
raise serializers.ValidationError('项目名称必须以"项目"结尾')
return value
def validate(self, attrs):
if '张三' not in attrs['developer'] and '张三' not in attrs['tester']:
raise serializers.ValidationError('"张三"必须是项目开发人员或测试人员')
return attrs
from rest_framework import serializers
from interfaces.models import Interfaces
from projects.serializer import ProjectModelSerializer
class InterfaceModelSerializer(serializers.ModelSerializer):
project = serializers.PrimaryKeyRelatedField(help_text='所属项目', label='所属项目', queryset=Projects.objects.all())
class Meta:
model = Interfaces
fields = "__all__"
from django.http import HttpResponse, JsonResponse, Http404
from django.views import View
from projects.models import Projects
from projects.serializer import ProjectModelSerializer
import json
class ProjectList(View):
""""
类视图
"""
def get(self, request):
projects = Projects.objects.all()
serializer = ProjectModelSerializer(instance=projects, many=True)
return JsonResponse(serializer.data, safe=False, status=200)
def post(self, request):
"""
httpie模拟请求:http POST :8000/projects/ name='项目009' leader="zz" developer='李四' tester='王五' app_name='测试应用' app_version='1.0' desc='demo desc'
"""
data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
serializer = ProjectModelSerializer(data=data)
try:
serializer.is_valid(raise_exception=True)
except Exception as e:
return JsonResponse(serializer.errors)
serializer.save()
return JsonResponse(serializer.data, safe=False, status=201)
class ProjectDetail(View):
def get_object(self, pk):
try:
return Projects.objects.get(id=pk)
except Projects.DoesNotExist:
raise Http404
def get(self, request, pk):
"""
httpie模拟请求:http :8000/projects/12
"""
project= self.get_object(pk)
serializer = ProjectModelSerializer(instance=project)
return JsonResponse(serializer.data, safe=False)
def put(self, request, pk):
"""
httpie模拟请求:http PUT :8000/projects/12 name='项目0091' leader="张三" developer='李四' tester='王五' app_name='测试应用' app_version='1.0' desc='demo desc'
"""
project = self.get_object(pk)
data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
serializer = ProjectModelSerializer(instance=project, data=data)
try:
serializer.is_valid(raise_exception=True)
except Exception as e:
return JsonResponse(serializer.errors)
serializer.save()
return JsonResponse(serializer.data, safe=False, status=201)
def delete(self, request, pk):
"""
httpie模拟请求:http DELETE :8000/projects/12
"""
project = self.get_object(pk)
project.delete()
return JsonResponse(None, safe=False, status=204)
from django.http import HttpResponse, JsonResponse, Http404
from django.views import View
from interfaces.models import Interfaces
from interfaces.serializer import InterfaceModelSerializer
import json
class InterfaceList(View):
""""
类视图
"""
def get(self, request):
"""
httpie模拟请求:http :8000/interfaces/
"""
interfaces = Interfaces.objects.all()
serializer = InterfaceModelSerializer(instance=interfaces, many=True)
return JsonResponse(serializer.data, safe=False, status=200)
def post(self, request):
"""
httpie模拟请求:http POST :8000/interfaces/ name='接口001' tester="吴用" desc='这是第一个测试接口' project_id=1
"""
data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
serializer = InterfaceModelSerializer(data=data)
try:
serializer.is_valid(raise_exception=True)
except Exception as e:
return JsonResponse(serializer.errors)
serializer.save()
return JsonResponse(serializer.data, safe=False, status=201)