写点什么

DjangoRestFramework 框架简介及基本使用

用户头像
行者AI
关注
发布于: 2021 年 01 月 28 日

本文首发于:行者AI


在 python 项目开发中,前后端分离的技术框架越来越成熟,在前后端进行通信时,通常需要用统一的格式进行通信,目前应用比较广泛的是 RESTful API。那后端如何快速编写基于 Django 的 RESTful API 呢?本篇将主要介绍使用 DjangoRestFramework(drf)框架来快速开发符合 REST 风格的 API。

1. drf 概念及特点

1.1 概念


drf 框架是基于 Django 框架,用于快速构建 Web RESTful API 的工具。

1.2 特点


(1) 提供了定义序列化器 Serializer 的方法,可以快速根据 Django ORM 或者其他库自动序列化、反序列化;

(2) 提供了丰富的类视图、MIXIN 扩展类,根据需求组合继承,简化视图的编写;

(3) 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;

(4) 支持多种身份认证和权限认证方式;

(5) 内置了限流系统;

(6) 可视化 API 接口;

(7) 可扩展性 , 插件丰富。

2. drf 的使用


drf 对代码的简化主要是对视图的增删改查、请求数据的反序列化和响应数据的序列化进行简化,所以主要介绍 drf 的序列化器和视图集的使用。

2.1 搭建项目


搭建项目环境,创建项目 exercise,创建 app 应用 student,代码如下:


# python==3.6.5virtualenv -p /python/python.exe /virtualenv/exerciseenvcd /virtualenv/exerciseenv/Scripts/activatepip install django==3.1.5 pymysql==1.0.2 djangorestframework==3.12.2cd /study/django-admin startproject exercisecd exercisedjango-admin startapp student
复制代码


目录结构如下:



然后打开项目在/exercise/settings.py文件中配置数据库,注册 app(student 和 rest_framework)。

2.2 创建模型


/student/models.py文件中,建立三张表:班级(Grade)、课程(Course)、学生(Student)。


class Grade(models.Model):  # 班级    name = models.CharField(max_length=16, null=False, unique=True)
class Meta: db_table = 'grade' ordering = ['id']

class Course(models.Model): # 课程 name = models.CharField(max_length=32, unique=True, null=False)
class Meta: db_table = 'course' ordering = ['id']

class Student(models.Model): # 学生 name = models.CharField(max_length=16, null=False) age = models.IntegerField(null=True) gender = models.BooleanField(null=False, default=0) g = models.ForeignKey(Grade, on_delete=models.CASCADE) c = models.ManyToManyField(Course)
class Meta: db_table = 'student' ordering = ['id']
复制代码

2.3 创建序列化器


/student/serializers.py文件中,建立三个模型对应的序列化器;序列化器有两个主要功能:序列化和反序列化。如果前端是 GET 请求,则构造查询集,将结果返回,这个过程为序列化;如果前端是 POST 请求,要对数据库进行改动,则需要拿到前端发来的数据,进行校验,校验通过将数据写入数据库,这个过程称为反序列化。这能极大的简化视图代码量,后面会做个对比。代码如下:


class GradeSerializer(serializers.ModelSerializer):    class Meta:        # 指定序列化器对应的模型        model = Grade        # 指定需要序列化的字段,‘__all__’表示所有字段        fields = ['name']

class CourseSerializer(serializers.ModelSerializer): class Meta: model = Course fields = ['name']

class StudentSerializer(serializers.ModelSerializer): # 自定义序列化和反序列化字段校验条件,默认使用建表约束校验;也可以使用extra_kwargs # SlugRelatedField指定关联对象的指定字段,关联字段默认为关联对象id c = serializers.SlugRelatedField(slug_field='name', many=True, queryset=Course.objects.all()) g = serializers.SlugRelatedField(slug_field='name', queryset=Grade.objects.all())
class Meta: model = Student # 自定义校验 extra_kwargs = {'age': {'max_value': 30, 'min_value': 0}} fields = '__all__'
# 返回数据预处理 def to_representation(self, instance): data = super().to_representation(instance) if data['gender'] == 0: data['gender'] = '女' else: data['gender'] = '男' return data
复制代码

2.4 编写视图


/student/views.py文件中,编写视图,每个模型对应一个视图,继承 drf 的``viewsets.ModelViewSet``类,包含增删改查四大操作,通过不同的请求方法映射到 drf 定义的对应的动作 action 方法上。action 方法包括 create(新增)、retrieve(查询详情)、destroy(删除)、update(修改)、list(列表展示)。代码如下:


class StudentView(viewsets.ModelViewSet):    queryset = Student.objects.all()  # 指定查询结果集    serializer_class = StudentSerializer  # 指定序列化器

class GradeView(viewsets.ModelViewSet): queryset = Grade.objects.all() serializer_class = GradeSerializer

class CourseView(viewsets.ModelViewSet): queryset = Course.objects.all() serializer_class = CourseSerializer
复制代码

2.5 注册路由

/exercise2/urls.py文件中,注册根路由:


urlpatterns = [    path('api/', include('student.urls'))]
复制代码

/student/urls.py文件中,注册资源路由:


# 使用drf的视图集就不需要编写路由,通过DefaultRouter的register方法注册就可以了router = DefaultRouter()router.register('student', views.StudentView)router.register('course', views.CourseView)router.register('grade', views.GradeView)
urlpatterns = [ path('', include(router.urls))]
复制代码

2.6 列举 url


列举一下资源为 student 的请求路径和方式,其他资源类似:


GET http://127.0.0.1:8000/api/student/  查询所有学生信息
POST http://127.0.0.1:8000/api/student/ 传入学生各项信息,创建该学生对象
GET http://127.0.0.1:8000/api/student/1/ 查询id为1的学生信息 默认过滤字段为id,可自定义过滤器
DELETE http://127.0.0.1:8000/api/student/1/ 删除id为1的学生,默认过滤字段为id
PUT http://127.0.0.1:8000/api/student/1/ 修改id为1的学生信息,默认过滤字段为id
复制代码

3. drf 框架与原生 Django 的对比

3.1 views.py 文件


这里只写了 student 模型对应的各项操作视图,其他模型类似。StudentListCrate 视图包含展示学生列表(get)和插入学生数据(post)接口,StudentUpdateRetrieveDestroy 视图包含对单个学生数据查询(get)、修改(put)、删除(delete)接口。代码如下:


class StudentListCrate(View):    def get(self, request):        students = Student.objects.all()        students_list = []        for stu in students:            if stu.gender == 1:                stu_gender = '男'            else:                stu_gender = '女'            g_name = Grade.objects.filter(id=stu.g_id).first().name            cou_name_list = []            for cou in stu.c.all():                cou_name_list.append(cou.name)            students_list.append({'id': stu.id, 'name': stu.name, 'age': stu.age,                                  'gender': stu_gender, 'courses': cou_name_list,                                  'g_name': g_name})        return JsonResponse(students_list, safe=False)
def post(self, request): form = StudentForm(json.loads(request.body)) if form.is_valid(): name = form.cleaned_data['name'] age = form.cleaned_data['age'] gender = form.cleaned_data['gender'] g = form.cleaned_data['g'].id c = [cou.id for cou in form.cleaned_data['c']] stu = Student.objects.create(name=name, age=age, gender=gender, g_id=g) stu.save() stu.c.add(*c) return JsonResponse({'code': 200, 'msg': '创建成功'}) return JsonResponse({'code': 200, 'msg': form.errors})

class StudentUpdateRetrieveDestroy(View): def get(self, request, pk): stu = Student.objects.filter(pk=pk).first() if not stu: return JsonResponse({'code': 400, 'msg': '没有这个学生'}) g_name = Grade.objects.filter(id=stu.g_id).first().name if stu.gender == 1: stu_gender = '男' else: stu_gender = '女' cou_name_list = [] for cou in stu.c.all(): cou_name_list.append(cou.name) return JsonResponse({'id': stu.id, 'name': stu.name, 'age': stu.age, 'gender': stu_gender, 'courses': cou_name_list, 'g_name': g_name})
def put(self, request, pk): stu_query = Student.objects.filter(pk=pk) stu = stu_query.first() if not stu: return JsonResponse({'code': 400, 'msg': '没有这个学生'}) form = StudentForm(json.loads(request.body)) if form.is_valid(): c = [cou.id for cou in form.cleaned_data['c']] stu.c.set(c) del form.cleaned_data['c'] update_dict = form.cleaned_data stu_query.update(**update_dict) return JsonResponse({'code': 200, 'msg': '创建成功'}) return JsonResponse({'code': 200, 'msg': form.errors})
def delete(self, request, pk): stu = Student.objects.filter(pk=pk).first() if not stu: return JsonResponse({'code': 400, 'msg': '没有这个学生'}) stu.delete() return JsonResponse({'code': 200, 'msg': '删除成功'})
复制代码

3.2 forms.py 文件


这是放置做表单校验类的文件,是在模型约束之上再定义一层符合业务实际意义的校验,并且校验未通过,可以将错误提示信息返回给用户,提高用户体验,代码如下:


class StudentForm(forms.Form):    name = forms.CharField(max_length=16, required=True, min_length=2,                           error_messages={'max_length': '名字最长为16',                                            'min_length': '名字最短为2',                                            'required': '名字必填'})    age = forms.IntegerField(max_value=30, min_value=10,                             error_messages={'max_value': '年龄最大为30',                                             'min_value': '年龄最小为10'})    gender = forms.BooleanField(required=False, error_messages={'required': '性别必填'})    g = forms.ModelChoiceField(queryset=Grade.objects.all(), error_messages={'queryset': '没有这个班级'})    c = forms.ModelMultipleChoiceField(queryset=Course.objects.all(), error_messages={'queryset': '不存在这个课程'})
复制代码

3.3 总结

对比发现 drf 处理三个模型的代码量比原生 django 处理一个模型的代码都要少,说明 drf 框架极大地提高了 RESTful API 开发效率,不过仔细点还能发现由于 drf 封装地太好,对于处理业务逻辑复杂的接口就需要我们重构相应的方法。drf 丰富的各项功能使我们开发效率更高,但同时学习成本也是直线上升,本文只是阐述序列化器和视图集类的应用,对于细分的各类的应用及组合使用还需进一步研究学习。

发布于: 2021 年 01 月 28 日阅读数: 20
用户头像

行者AI

关注

行者AI,为游戏插上人工智能的翅膀。 2020.12.18 加入

行者AI(成都潜在人工智能科技有限公司)专注于人工智能在游戏领域的研究和应用,凭借自研算法,推出游戏AI、智能内容审核、数据平台等产品服务。

评论

发布
暂无评论
DjangoRestFramework框架简介及基本使用