Django 用户认证 用户 邮箱登录 邮箱注册 ORM or,and,not form.py FORM ModelForm Paginator 分页 HTMl JQuery 定位元素 ajax django切片 restfulapi 跨域 Ubantu Python Mysql Scrapy 爬虫 导出 Python读写 Pycharm 破解 session re sqlit3 生成式 其他 Prism 富文本 CSS Nginx 部署 请求头 抓包 协议 selenium Ubuntu 宝塔 AI Comfy-ui ollama dify open-webui Git docker
restfulapi介绍
张建行 2022年6月24日 19:12 52 文章标签: Django restfulapi

如果一个前后端分离项目需要对用户表进行增删改查的需求
普通的后端代码需要这样写:
http://www.baidu.com/add_user/
一个接口需要有一个返回值。因此后端接口还需要提供接口文档,说明这个接口的相关信息。
http://www.baidu.com/update_user/
http://www.baidu.com/get_user/
http://www.baidu.com/delete_user/

前端代码需要发送ajax请求,去请求上述的url,也就是接口。
$.ajax({})

1.接口(api)开发:注意这里将的接口开发并不涉及到restful,就是单纯的接口开发。
第一种普通的思路:
urlpatterns = [
url(r’^get_order/’, views.get_order),
url(r’^add_order/’, views.add_order),
url(r’^del_order/’, views.del_order),
url(r’^update_order/’, views.update_order),
]
def get_order(request):
return HttpResponse(’’)
def add_order(request):
return HttpResponse(’’)
def del_order(request):
return HttpResponse(’’)
def update_order(request):
return HttpResponse(’’)
上面这种也是接口开发,但是不建议这样写,因为一个order数据的操作就要设置四个url。如果数据多的话,前后端的url的数量也会成倍的增加。
渐渐的出来一种规范,如果大家都安装这种规范来做的话,会大大的减少url的数量,url更加简洁,此时就出现了restful规范。
2.restful api规范
a. 同一种数据的操作,只设置一个url路由。也就是根据请求方法来区分具体的处理逻辑。而不再设置多个增删改查的路由。
(1)可以基于FBV来通过请求方法的不同,处理不同的逻辑。
url(r’^order/’, views.order),
def order(request):
if request.method == ‘GET’:
return HttpResponse(‘获取订单’)
elif request.method == ‘POST’:
return HttpResponse(‘创建订单’)
elif request.method == ‘PUT’:
return HttpResponse(‘更新订单’)
elif request.method == ‘DELETE’:
return HttpResponse(‘删除订单’)
(2)可以基于CBV来实现处理不同的逻辑
url(r’^order/’, views.OrderView.as_view()),
class OrderView(View):
def get(self,request,*args,**kwargs):
return HttpResponse(json.dumps(ret),status=201)
def post(self,request,*args,**kwargs):
return HttpResponse(‘创建订单’)
def put(self,request,*args,**kwargs):
return HttpResponse(‘更新订单’)
def delete(self,request,*args,**kwargs):
return HttpResponse(‘删除订单’)

    而两种方式中,最建议使用CBV的方式去写接口,更加简洁,不用判断了。
b. 域名建议
    为了对用户使用的url和网页中使用的接口api进行区别,设置如下规则
    (1)子域名的方式区分(需要解决跨域的问题):
        www.baidu.com (用户在浏览器中输入的地址,可以访问网站页面)
        但是网页需要到后台请求接口,获取数据,那么接口的api应该如何命名呢?
        api.baidu.com/v1/login.json
        用户一看到域名是以api开头的,就知道是接口,返回的是json数据。
    (2)URL的方式进行区分(不需要解决跨域问题):
        www.baidu.com (用户使用的URL)
        www.baidu.com/api/v1/login.json
    不管使用哪种方式,就是为了能够一眼区分出来这是一个api接口。
    
    两种方式哪一种更好呢?
    答案是第二种,因为第一种可能会出现跨域请求,也就是当域名不同或者端口不同的时候,都会出现跨域请求,而第二种保证了域名和端口的一致性,只是url不一样而已。
    跨域:因为浏览器的同源策略,当你通过浏览器向www.baidu.com前端页面发送请求的时候,网页需要向后台请求接口,但是如果接口的域名和当前的域名不一致,就会出现跨域请求的错误,无法访问到页面。而跨源是网页向api发送请求之后,服务器响应了这个请求,但是是浏览器端把这一次请求的响应给阻止了,并不是在请求不同域名的接口时,服务端不会响应这个请求。跨源是浏览器端的阻止行为,而不是服务器端的。
    
c. 版本规则
    两个版本共存的时候,应该将API的版本号放入URL。
    api.example.com/api/v1/
    另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。

d. 面向资源编程
    将网络中的任何东西都看作是资源,对资源可以进行增删改查的操作,但是资源表示的是一个名称,如果一个url后面跟的是一个名词(单复数都可以),所用的名词往往与数据库的表格名对应,就表示要对这个资源进行增删改查的操作了。而get/post/delete/put是动词,所以url中不建议出现动词。
    www.baidu.com/api/v1/order/ (遵循规范)
    www.baidu.com/api/v1/orders/ (遵循规范)
    www.baidu.com/api/v1/get_order/ (没有遵循规范)

e. HTTP方法规范
    GET:从服务器上获取一个或者多个资源
    POST:在服务器上新建一个资源
    PUT:在服务器跟新全部资源
    PATCH:在服务器更新部分资源
    比如用户表就有用户名,密码,性别,如果是PUT就全部更新。如果是PATHCH就只更新密码。
    
f. 过滤规范
    www.baidu.com/api/v1/orders/?status=1&page=2&offset

g. 状态码规范(状态码+code码)
    后台提供的状态码,供前端使用。
    200系列,300系列表示重定向,400系列表示客户端错误,500系列表示服务端错误(后台代码错误)。
    但是只有状态码还是不够的,请求的状态太多,所以除了使用状态码表示状态以外,还应该有code码来表示更加详细的请求情况。
    比如:支付宝的code码,20000,20001等
    
    def get(self,request,*args,**kwargs):
        ret  = {
            'code':1000,
            'msg':'没有携带cookie'
        }
        return HttpResponse(json.dumps(ret),status=201)
        
h. 请求的返回值规范
    GET /order/:返回资源对象的列表(数组)
    GET /order/1/:返回单个资源对象
    POST /order/:返回新生成的资源对象
    PUT /order/1/:返回完整的资源对象
    PATCH /order/1/:返回完整的资源对象
    DELETE /order/1/:返回一个空文档

i. Hypermedia API超链接规范
    希望在请求结果中包含这一个资源的详细信息的api。
    比如,我们请求商品列表信息得到如下的结果:
    [
        {
            "id": 1,
            "name": "袜子"
        },
        {
            "id": 2,
            "name": "裤子"
        },
        {
            "id": 3,
            "name": "鞋子"
        }
    ]
    如果你想查看id=1的商品的详细信息,你需要使用这个id拼接详情页的url地址,并发出请求,但是restful中希望这个详情页的url直接包含在json数据中,不用再单独进行拼接了。
    [
        {
            "id": 1,
            "name": "袜子",
            "url": "http://www.baidu.com/api/v1/1/"
        },
        {
            "id": 2,
            "name": "裤子"
            "url": "http://www.baidu.com/api/v1/2/"
        },
        {
            "id": 3,
            "name": "鞋子"
            "url": "http://www.baidu.com/api/v1/2/"
        }
    ]