Django Rest Framework —— Rest

前言

原因: 前几天基于Django做了TodoList案例之后, 有前端同学拿着我的Django后端API访问,给我一顿喷,说我的API设计的怎么这么乱,然后就走了, 走的时候就留下了一句: 都2023年了,你居然还不知道RestFul

🚀 所以我下去之后立马看了看什么是RestFul

在前后端分离开发模式中, 对于接口的请求方式与路径,每个后端开发人员都有自己独特的定义方式与风格,这就导致了你对接不同的后端,就要适应不同风格的Api

那么是否存在一种统一的定义方式,能够被广大的开发人员所接受呢? —— RestFul, 这也就是我们今天的主题

RestFul

RestFul Api只是一种接口风格, 即使你不遵守这个风格, 你的代码逻辑, 前后端联调也是能够正常完成的(上面我个人的案例就能够证明)

下面我放一组RestFul风格的API, 和我之前的做一下对比,相信你们就会一目了然

请求方法

请求路径

含义

GET

/books

查询所有的图书信息

POST

/books

添加图书

GET

/books/1

查询id为1的图书详情

PUT

/books/1

更新id为1的图书信息

DELETE

/books/1

删除id为1的图书

请求方法

请求路径

含义

GET

/list

查询所有任务信息

POST

/create

创建任务

POST

/update

更新任务信息

DELETE

/delete

删除任务信息

看完这两张表之后我相信大家更喜欢也更乐意去调用第一种风格的Api

这里我列举几点RestFul Api的风格

1、资源作为网址,不能有动词

上面我的api风格就全是动词, create, update,delete, 但是反之RestFul采用名词, books, 而且这里的名词一般多数使用复数形式

2、搭配合理的HTTP动词

  • GET 从服务器中取出资源
  • POST 在服务器中新建一个资源
  • PUT 更新服务器资源
  • DELETE 从服务器中删除资源

        除了这几个我们耳熟能详的HTTP动词,还有三个不常用的,借此机会,我们也要了解一下

  • PATCH 在服务器更新资源
  • HEAD 获取资源的元数据
  • OPTIONS 获取信息, 关于资源的哪些属性是客户端可以改变的

3、过滤信息

Api也应该主动提供参数,过滤返回的结果, 下面是一些常见的参数

?limit=10 指定返回记录数量
?pageSize=10&pageNum=1 指定访问第几页,以及每页的数量
?orderBy=age&order=asc 指定返回结果按照哪个属性排序,以及排序的顺序

4、状态码

200 OK - [GET: 服务器成功返回用户请求的数据
201 CREATED -[POST/PUT/PATCHJ: 用户新建或修改数据成功。
202 Accepted -[]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT -[DELETE]:用户制除数据成功。
400 INVALID REQUEST-[POST/PUT/PATCH]: 用户发出的请求有错误,服务器没有进行新建或修改数据的操作
401 Unauthorized-[l:表示用户没有权限 (令牌、用户名、密码错误)。

403 Forbidden -[ 表示用户得到授权 (与401错误相对),但是访问是被禁止的。

404 NOT FOUND-[]: 用户发出的请求针对的是不存在的记录,服务器没有进行操作.
406 Not Acceptable - [GET]: 用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GEI: 用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity -[POST/PUT/PATCH]当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR-[: 服务器发生错误,用户将无法判断发出的请求是否成功

5、返回值

返回值应该是JSON格式的数据,除了DELETE方法可以没有返回体,其他的都应该有合适的返回体。

6、错误处理

如果状态码是4xx, 服务器应该向用户返回错误信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。

{
    error: "has no token"
}

实践

 知道了什么事Restful,就要动手实践一下,把我们之前写过的todoList案例中的接口改造成RestFul风格。

 以下是五个要写的基本接口

todoList/views.py

"""
get /todos
post /todos
get /todos/pk
post /todos/pk
delete /todos/pk
"""

引入基础包以及定义基础返回内容

from django.http import JsonResponse, HttpResponse
from .models import TodoList
from django.views import View
import json

BaseResponseData = {
    'code': 200,
    'message': '',
    'data': None
}

获取所有的todo列表信息和 增加todo的接口


class TodoListView(View):

    def get(self, request):
        todos = TodoList.objects.filter(is_delete=0)
        todo_list = []
        for todo in todos:
            todo_dict = {
                'id': todo.id,
                'title': todo.title,
                'completed': todo.completed,
                'create_time': todo.create_time,
                'update_time': todo.update_time,
            }
            todo_list.append(todo_dict)
        return JsonResponse(todo_list, safe=False)

    def post(self, request):
        print(request)
        post_dict = json.loads( request.body )
        todo = TodoList.objects.create(title=post_dict.get("title"))
        response_dict = {
            'code': 200,
            'message': "创建成功",
            'todo': {
                'id': todo.id,
                'title': todo.title,
                'completed': todo.completed,
                'create_time': todo.create_time,
                'update_time': todo.update_time,
            }
        }
        return JsonResponse(response_dict, safe=False)

获取、删除、修改单个todo信息的接口


class TodoDetailView(View):

    def get(self, request, pk):
        try:
            todo = TodoList.objects.get(pk=pk, is_delete=0)
        except TodoList.DoesNotExist:
            return JsonResponse({"message": "任务不存在"}, status=404)
        todo_dict = {
            'id': todo.id,
            'title': todo.title,
            'completed': todo.completed,
            'create_time': todo.create_time,
            'update_time': todo.update_time,
        }
        return JsonResponse(todo_dict, safe=False)

    def put(self, request, pk):
        try:
            todo = TodoList.objects.get(pk=pk, is_delete=0)
        except TodoList.DoesNotExist:
            return JsonResponse({"message": "任务不存在"}, status=404)
        todo.completed = 1 if todo.completed == 0 else 0
        todo.save()
        response_dict = {
            'code': 200,
            'message': "任务更新成功",
            'todo': {
                'id': todo.id,
                'title': todo.title,
                'completed': todo.completed,
                'create_time': todo.create_time,
                'update_time': todo.update_time,
            }
        }
        return JsonResponse(response_dict, safe=False)

    def delete(self, request, pk):
        try:
            todo = TodoList.objects.get(pk=pk, is_delete=0)
        except TodoList.DoesNotExist:
            return JsonResponse({"message": "任务不存在"}, status=404)
        todo.is_delete = 1
        todo.save()
        response_dict ={
            'code': 200,
            'message': "删除成功"
        }
        return JsonResponse(response_dict, safe=False)

todoList/urls.py

from django.urls import path
from todoList import def_views as todo_views
from todoList import views
urlpatterns = [
    # 未使用ResfFul风格对应的url
    path("create", todo_views.create_todo_view),
    path('update', todo_views.update_todo_view),
    path("delete", todo_views.delete_todo_view),
    path('list', todo_views.todo_list_view),

    # RestFul风格的url, 对比来看更加简洁,优雅
    path("todos", views.TodoListView.as_view()),
    path("todos/<int:pk>", views.TodoDetailView.as_view()),
]

到这里为止,todoList代码就改造完成了。

和之前是有些不一样的,细心的话可以注意到这里写的是类视图,之前写的是函数视图,这里大概列出他们之间有什么区别:

1、类视图中可以写方法,比如get,put,delete对应的就是调用Api时的HTTP动词; 而在方法视图中则是需要通过reques.method去拿到访问此APi当前的HTTP动词是什么,再去判断使用什么样的方法,就会出现很多的if-else

2、类视图中的方法第一个参数是self,可以调用自己内部的其他属性和函数

3、类视图需要继承一个基础的视图类,这里使用的是 from django.views import View,这里剧透一下,之后我们还会学习很多诸如此类的基础视图类

这里我放一段方法视图的代码,大家可以观察一下他们的区别

def delete_todo_view(request):
    if request.method == 'DELETE':
        id = request.GET.get('id')
        TodoList.objects.filter(pk=id).update(is_delete=1)
        BaseResponseData['message'] = '任务删除成功'
    else:
        BaseResponseData['message'] = '方法错误'
    return HttpResponse(json.dumps(BaseResponseData))

从本篇文章之后的所有的Api都会使用RestFul风格的类视图去编写。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值