一、django的FBV 和 CBV
1、FBV(基于函数的视图):
urlpatterns = [ url(r'^users/', views.users), ]
def users(request): user_list = ["amy", "jack", "lily"] return HttpResponse(json.dumps(user_list))
2、CBV(基于类的视图):
urlpatterns = [ url(r'^students/', views.StudentsView.as_view()), ]
from django.views import View
class StudentsView(View): def get(self, request, *args, **kwargs): """get方法访问""" return HttpResponse("get") def post(self, request, *args, **kwargs): """post方法访问""" return HttpResponse("post") def put(self, request, *args, **kwargs): """put方法访问""" return HttpResponse("put") def delete(self, request, *args, **kwargs): """delete方法访问""" return HttpResponse("delete")
3、CBV实现原理
dispatch()方法的实现相当于:
from django.views import View class StudentsView(View): def dispatch(self, request, *args, **kwargs): func = getattr(self, request.method.lower()) # 通过反射获取请求方法(记得把获取到的方法名变成小写) return func(request, *args, **kwargs) # 执行这个方法并将结果返回给用户
CBV就是通过路由,执行view()函数,再通过dispatch()方法基于反射,根据不同的请求方式来执行这些请求方法,如get、post、patch等。
若是继承父类的dispatch方法:
class StudentsView(View): def dispatch(self, request, *args, **kwargs): # 继承父类的dispatch方法 return super(StudentsView, self).dispatch(request, *args, **kwargs)
4、多个类继承基类
多个类公用的功能可以用继承来实现:
from django.views import View class MyBaseView(object): def dispatch(self, request, *args, **kwargs): # 继承父类的dispatch方法 return super(MyBaseView, self).dispatch(request, *args, **kwargs) class StudentsView(MyBaseView, View): def get(self, request, *args, **kwargs): """get方法访问""" return HttpResponse("get") def post(self, request, *args, **kwargs): """post方法访问""" return HttpResponse("post") def put(self, request, *args, **kwargs): """put方法访问""" return HttpResponse("put") def delete(self, request, *args, **kwargs): """delete方法访问""" return HttpResponse("delete") class TeachersView(MyBaseView, View): def get(self, request, *args, **kwargs): """get方法访问""" return HttpResponse("get") def post(self, request, *args, **kwargs): """post方法访问""" return HttpResponse("post") def put(self, request, *args, **kwargs): """put方法访问""" return HttpResponse("put") def delete(self, request, *args, **kwargs): """delete方法访问""" return HttpResponse("delete")
5、CBV的csrf认证
方法1:给dispatch()方法加上装饰器,即可让该视图免于csrftoken认证:
import json from django.shortcuts import render, HttpResponse from django.views import View from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator class StudentsView(View): @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): return super(StudentsView, self).dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs): """get方法访问""" return HttpResponse("get") def post(self, request, *args, **kwargs): """post方法访问""" return HttpResponse("post") def put(self, request, *args, **kwargs): """put方法访问""" return HttpResponse("put") def delete(self, request, *args, **kwargs): """delete方法访问""" return HttpResponse("delete")
方法2:给类加上装饰器,使得该视图免于csrftoken认证:
from django.shortcuts import render, HttpResponse from django.views import View from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator @method_decorator(csrf_exempt, name="dispatch") class StudentsView(View): def get(self, request, *args, **kwargs): """get方法访问""" return HttpResponse("get") def post(self, request, *args, **kwargs): """post方法访问""" return HttpResponse("post") def put(self, request, *args, **kwargs): """put方法访问""" return HttpResponse("put") def delete(self, request, *args, **kwargs): """delete方法访问""" return HttpResponse("delete")
二、基于Django实现restful api
1、例:订单的增删改查
对于普通的接口开发:
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^get_order/', views.get_order), url(r'^del_order/', views.del_order), url(r'^add_order/', views.add_order), url(r'^update_order/', views.update_order), ]
from django.shortcuts import render, HttpResponse def get_order(request): return HttpResponse("get_order") def del_order(request): return HttpResponse("del_order") def update_order(request): return HttpResponse("update_order") def add_order(request): return HttpResponse("add_order")
这种方式在url比较多的情况下并不实用,所以我们引出了restful规范,根据请求方式的不同来进行不同的操作:
get请求→查询
post请求→创建
delete请求→删除
put请求→更新
(1)基于FBV的写法:
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^order/', views.order), ]
from django.shortcuts import render, HttpResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt def order(request): if request.method == "GET": return HttpResponse("查询订单") elif request.method == "POST": return HttpResponse("创建订单") elif request.method == "DELETE": return HttpResponse("删除订单") elif request.method == "PUT": return HttpResponse("更新订单")
(2)基于CBV的写法:
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^order/', views.OrderView.as_view()), ]
from django.shortcuts import render, HttpResponse from django.views import View from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator @method_decorator(csrf_exempt, name="dispatch") class OrderView(View): def get(self, request, *args, **kwargs): return HttpResponse("查询订单") def post(self, request, *args, **kwargs): return HttpResponse("创建订单") def delete(self, request, *args, **kwargs): return HttpResponse("删除订单") def put(self, request, *args, **kwargs): return HttpResponse("更新订单")
三、RESTful协议
REST与技术无关,它代表的是一种面向资源软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”。
1、API与用户的通信协议,总是使用https协议
2、域名
要让别人看到这个URL就知道这是一个网站,还是一个要返回数据的接口
- 子域名的方式(存在跨域问题)
www.baidu.com # 用户访问这个 api.baidu,com # 返回json数据
- URL方式
www.baidu.com # 用户访问这个 www.baidu,com/aip/ # 返回json数据
3、版本
在URL上应该体现版本,例如Bootstrap,有https://v2.bootcss.com/,有https://v3.bootcss.com/等。
- 加到URL上:https://www.baidu.com/api/v1/
- 加到请求头上(跨域时,会引发多次请求)
4、路径
将网络上的一切东西都看作资源,建议尽量将URL的后缀使用名词表示(也可以用复数):
https://www.baidu.com/api/v1/user/
https://www.baidu.com/api/v1/users/
5、method
根据不同类型的请求来做不同的操作。
- GET 从服务器取出资源(一项或多项)
- POST 在服务器新建一个资源
- PUT 在服务器更新资源(客户端提供改变后的完整资源,全部更新)
- PATCH 在服务器更新资源(客户端提供改变后的属性,局部更新)
- DELETE 从服务器删除资源
6、过滤
在URL上面加条件
https://www.baidu.com/api/v1/user/?status=1&page=2 # 表示status=1的、第2页的用户
7、状态码
建议在响应中添加状态码
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务) 204 NO CONTENT - [DELETE]:用户删除数据成功。 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。 更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
例:
8、错误处理
比如进行登录操作,如果用户名或者密码错误,就会给用户返回一个错误信息。
状态码为4xx时,应返回错误信息:
{
code: 1001, error: "Invalid API key" }
9、返回结果
根据不同的操作,返回不同的结果:
GET /order/:返回所有订单列表(数组) GET /order/1/:返回单个订单的详细信息(资源对象) POST /order/:返回新生成的订单 PUT /order/1/:返回修改后完整的订单信息 PATCH /order/1/:返回修改后的订单信息(局部) DELETE /oder/1/:删除订单 返回一个空文档
10、Hypermedia API
在返回结果中提供链接,连向其他API方法,使得用户不用查文档,通过这个链接来获取数据
四、Django rest framework框架
1、安装
pip3 install djangorestframework
2、Django rest framework认证源码及实现
rest_framework的dispatch方法:
如何获取加工后的request的值:
到这个加工过的Request里面去看看user都干了些什么:
实现认证:
可以自定制认证类:
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^course/', views.CourseView.as_view()), ]
from django.shortcuts import render, HttpResponse from django.views import View from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator from rest_framework.views import APIView from rest_framework.authentication import BasicAuthentication from rest_framework import exceptions class MyAuthentication(object): """自定制认证""" def authenticate(self, request): # 去请求里面获取信息,到数据库中进行校验,如果校验失败就抛出异常 token = request._request.GET.get("token") if not token: raise exceptions.AuthenticationFailed("用户认证失败") return ("amy", None) def authenticate_header(self, val): pass @method_decorator(csrf_exempt, name="dispatch") class CourseView(APIView): authentication_classes = [MyAuthentication] # 使用自定义的 authentication_classes def get(self, request, *args, **kwargs): print(request.user) # 打印 amy return HttpResponse("查询课程") def post(self, request, *args, **kwargs): return HttpResponse("创建课程") def delete(self, request, *args, **kwargs): return HttpResponse("删除课程") def put(self, request, *args, **kwargs): return HttpResponse("更新课程")