关于restful:DjangoRestFramework框架简介及基本使用

10次阅读

共计 6600 个字符,预计需要花费 17 分钟才能阅读完成。

本文首发于:行者 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.5
virtualenv -p /python/python.exe /virtualenv/exerciseenv
cd /virtualenv/exerciseenv/Scripts/
activate
pip install django==3.1.5 pymysql==1.0.2 djangorestframework==3.12.2
cd /study/
django-admin startproject exercise
cd exercise
django-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 丰盛的各项性能使咱们开发效率更高,但同时学习老本也是直线回升,本文只是论述序列化器和视图集类的利用,对于细分的各类的利用及组合应用还需进一步钻研学习。

正文完
 0