logo头像
Snippet 博客主题

Python3 - Django rest_framework实现 API

一、什么是REST

面向资源是REST最明显的特征,资源是一种看待服务器的方式,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以它不仅仅能代表服务器文件系统中的一个文件、数据库中的一张表等等具体的东西,可以将资源设计的要多抽象有多抽象,只要想象力允许而且客户端应用开发者能够理解。

与面向对象设计类似,资源是以名词为核心来组织的,首先关注的是名词。一个资源可以由一个或多个URI来标识。URI既是资源的名称,也是资源在Web上的地址。对某个资源感兴趣的客户端应用,可以通过资源的URI与其进行交互。对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。

REST要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。(7个HTTP方法:GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS)

二、什么是RESTful

API符合REST架构设计的API。

概念不多说了,具体通过下面的一个简单例子看看Django框架是怎么实现RESTful。

三、rest_framework模块

  1. 使用pip命令下载:pip3 install djangorestframework

  2. 创建项目: 之前的博客已经详细介绍了创建django项目的方法,这里不再多说。

  3. 打开settings.py,增加一段配置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'apitest', # 添加apitest app
    'rest_framework', # 添加rest_framework
    ]


    #增加一段REST_FRAMEWORK配置
    REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    # 'DEFAULT_PAGINATION_CLASS': 'utils.pagination.LinkHeaderPagination',
    # 分页条数
    'PAGE_SIZE': 3,
    # 权限
    'DEFAULT_AUTHENTICATION_CLASSES': (),

    # 重构renderer
    'DEFAULT_RENDERER_CLASSES': ('utils.function.CustomJsonRenderer',),

    # 配置过滤
    'DEFAULT_FILTER_BACKENDS': (
    'rest_framework.filters.DjangoFilterBackend',
    'rest_framework.filters.SearchFilter',
    )
    }
    1. 打开model.py,创建model
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    from django.db import models

    # Create your models here.
    class Grade(models.Model):
    g_name = models.CharField(max_length=20)
    g_create_time = models.DateTimeField(auto_now_add=True)

    class Meta:
    db_table = 'grade'


    class Student(models.Model):
    s_name = models.CharField(max_length=20, null=False, unique=True)
    s_create_time = models.DateTimeField(auto_now_add=True)# 添加是创建 不可更改
    s_operate_time = models.DateTimeField(auto_now=True)
    s_img = models.ImageField(upload_to='upload', null=True)
    g = models.ForeignKey(Grade)
    s_python = models.IntegerField(null=True)
    s_html = models.IntegerField(null=True)
    delete = models.BooleanField(default=False)

    class Meta:
    db_table = 'student'

    def __unicode__(self):
    return '%s: %s' % (self.s_name, self.s_python)
  1. app/urls.py 配置API路由

    1
    2
    3
    4
    5
    6
    7
    8
    from rest_framework.routers import SimpleRouter
    # 自定义router路由
    router = SimpleRouter()

    router.register(r'^api/student', api_views.api_student)
    router.register(r'^api/grade', api_views.api_grade)

    urlpatterns += router.urls
  2. 创建serializer.py文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    from collections import OrderedDict

    from rest_framework import serializers, response

    from app.models import Student, Grade


    class StudentSerializer(serializers.ModelSerializer):

    # 自定义错误信息
    s_name = serializers.CharField(max_length=20,error_messages={
    'blank': '姓名不能为空',
    })
    class Meta:
    # 指定model
    model = Student
    # 需要展示的字段
    fields = ['id','s_name', 's_html','s_python','s_img' ,'g']

    # 重写方法显示班级名称信息
    def to_representation(self, instance):
    # 循环序列化出学生对象
    data = super().to_representation(instance)
    # 给学生对象添加一个班级名称字段
    data['g_name'] = instance.g.g_name
    return data


    class GradeSerializer(serializers.ModelSerializer):
    # student_set = StudentSerializer(many=True)

    class Meta:
    model = Grade
    # fields = ['g_name', 'student_set']
    fields = ['id', 'g_name']


    def do_update(self, instance, validated_data):
    instance.g_name = validated_data['g_name']
    instance.save()

    data = self.to_representation(instance)

    return data
  3. 视图文件 api_views.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    from rest_framework import mixins, viewsets
    from rest_framework.response import Response

    from app.filters import StudentFilter, GradeFilter
    from app.models import Student, Grade
    from app.serializer import StudentSerializer, GradeSerializer


    class api_student(mixins.ListModelMixin,
    mixins.CreateModelMixin,
    mixins.UpdateModelMixin,
    mixins.RetrieveModelMixin,
    mixins.DestroyModelMixin,
    viewsets.GenericViewSet):
    # 查询学生的所有信息
    queryset = Student.objects.filter(delete=0)

    # 序列化学生的所有信息
    serializer_class = StudentSerializer

    # 过滤
    filter_class = StudentFilter

    # 子类重构父类函数, 实现过滤
    def get_queryset(self):
    return self.queryset.order_by('id')

    # 软删除 更改数据库数据, 不显示在前端
    def perform_destroy(self, instance):
    instance.delete = True
    instance.save()


    class api_grade(mixins.ListModelMixin,
    mixins.UpdateModelMixin,
    mixins.CreateModelMixin,
    mixins.RetrieveModelMixin,
    viewsets.GenericViewSet):
    # 查询课程所有信息
    queryset = Grade.objects.all()
    # 序列化所有课程信息
    serializer_class = GradeSerializer
    # 过滤
    filter_class = GradeFilter

    def update(self, request, *args, **kwargs):
    # 获取当前对象
    instance = self.get_object()
    # 序列化对象, 调用重写的方法
    serializer = self.serializer_class(instance, request.data)
    serializer.is_valid(raise_exception=True)
    # 调用重写的 do_update方法 保存数据
    serializer.do_update(instance, request.data)
    data = serializer.data
    data['code'] = 200
    data['msg'] = '请求成功'

    return Response(data)

    api/student/返回结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
code: 0,
msg: "请求成功",
data: {
count: 8,
next: "http://127.0.0.1:8000/app/api/student/?page=2",
previous: null,
results: [{
id: 3,
s_name: "小飞刀",
s_html: 85,
s_python: 71,
s_img: null,
g: 1,
g_name: "python2"
},
{
id: 4,
s_name: "小小飞刀",
s_html: 82,
s_python: 90,
s_img: null,
g: 1,
g_name: "python2"
},
{
id: 5,
s_name: "小王",
s_html: 78,
s_python: 100,
s_img: null,
g: 1,
g_name: "python2"
}
]
}
}

评论系统未开启,无法评论!