一、cbv源码分析
二、resful规范
三、django中写resful的借口
四、drf写resful的借口
五、APIVIew源码分析
六、drf之序列化
一、cbv源码分析
-CBV和FBV
1.在views中写一个类,继承views里面写get方法,post方法
2.在路由中配置:url(r'^test/',views.Test.as_view()),实际上上第二个参数位置,放的还是一个函数内存地址
3.当请求来了,就会执行第二个参数(request,参数),本质上执行views()
4.views内部调用了dispatch()方法
5.dispatch分发方法,根据请求方式不同,执行的方法不同
二、resful规范
-什么是restful?
1.REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
2.REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
3.REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
4.所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
5.对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture
-10个规范
1:与后台做交互,通常使用https
2:域名:
https://api.baidu.com(存在跨域问题)
https://baidu.com/api/
3:版本:
-https://www.baidu.com/api/v1
-https://www.baidu.com/api/v2
4.路径:视网上任何东西都是资源,群使用名词表示(可复数)
-https://api.example.com/v1/books
不是:https://api.example.com/v1/delete_one_book
5.method:
-https://api.example.com/v1/books get请求,获取所有书
-https://api.example.com/v1/books post请求,新增一本书
-https://api.example.com/v1/book/1 delete请求,删除一本书
-https://api.example.com/v1/book/1 delete请求,获取id为1的这本书
-https://api.example.com/v1/book/1 put/patch请求,修改id为1的这本书
6.过滤,通过在url上传参的形式的传递搜索条件
-https://api.example.com/v1/books?limit=10:只拿前10本
-https://api.example.com/v1/books?price=10:只拿价格为10的书
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.错误处理,应返回错误信息,error当做key
{
status:101,
errors:'您没有权限操作这个事'
}
9.返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范
GET/collection:返回资源对象的列表(数组)
GET/collection/resource:返回单个资源对象
POST/collection:返回新生成的自愿对象
PUT/collection/resource:返回完整的资源对象
PATH/collection/resource:返回完整的资源对象
DELETE/collection/resource:返回一个空文档
10.返回结果中提供链接(获取一本书)
{
id:1
name:lxx
price:12
publish:www.xx.com/api/v1/publish/1
}
三、django中写resful的借口
-请求地址戴反斜杠出现的问题(中间件)
-如果请求地址是/user,路由中配置成‘/user/’,匹配不上,中间件会自动在后面加/,再去匹配,能匹配成功,重定向到/user/,加了 / 还匹配不上,就报错
-django.middleware.common.CommonMiddleware
-基于Django实现
#路由
urlpatterns = [
url(r'^users/$', views.Users.as_view()),
url(r'^users2/$', views.user2), ]
#视图函数
import json def user2(request):
if request.method=='GET':
dic = {'status':200,'name': 'lqz2', 'age': 18}
return HttpResponse(json.dumps(dic))
elif request.method=='POST':
dic = {'status': 200, 'msg': '修改成功'}
return JsonResponse(dic) class Users(View):
def get(self, request):
dic = {'status':200,'name': 'lqz', 'age': 18}
return HttpResponse(json.dumps(dic)) def post(self, request):
dic = {'status': 200, 'msg': '修改成功'}
return JsonResponse(dic)
四、drf写resful的接口及APIVIew源码分析
1.先安装,pip3 install djangorestframework
方式一:pip3 install djangorestframework
方式二:pycharm图形化界面安装
方式三:pycharm命令行下安装(装在当前工程所用的解释器下)
2.djangorestframework的APIView分析
@classmethod
def as_view(cls, **initkwargs):
"""
Store the original class on the view function. This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
"""
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation view = super(APIView, cls).as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs # Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
as_view方法
def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate? try:
self.initial(request, *args, **kwargs) # Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc:
response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
dispatch
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request) return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
initialize_request
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs) # Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
initial方法(内部调用认证,权限和频率)
3.djangorestframework的Request对象简单介绍
4.基于drf写接口,写cbv
# 基于drf写接口,写cbv
class DrfTest(APIView):
def get(self, request, *args, **kwargs):
# request是封装之后的request了,原来的request是request._request
print(type(request._request))
print(type(request))
# 问:当前request对象并没有这些属性,但是能打印出来,为什么?
# getattr
print(request.method)
print(request.POST)
print(request.GET)
# 就相当于:
print(request.query_params)
print(request._request.GET)
response = {'status': 100, 'errors': None}
response['users'] = user_list
# 用drf的Response,可以通过请求客户端来判断返回数据格式是什么样的
return Response(response)
# return JsonResponse(response) def post(self, request, *args, **kwargs):
# post 提交的数据,urlencode,formdate,json格式,都能从data中取出来
name = request.data.get('name')
# request.FILES
print(name)
return HttpResponse('ok')
五、drf之序列化
干什么用的?把python中的对象,转成json格式字符串
1.写一个类继承
from rest_framework import serializers class BookSerializer(serializers.Serializer):
id = serializers.CharField()
name = serializers.CharField(source='title')
price = serializers.CharField()
publish_name = serializers.CharField(source='publish')
author_name = serializers.CharField(source='authors')
def get_author_name(self,obj):
return {'name':obj.name,'age':obj.age}
2.路由配置
from django.conf.urls import url
from django.contrib import admin
from app import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^books/', views.Books.as_view()),
url(r'^book/(?P<id>\d+)', views.Book.as_view()),
]
3.views视图函数
from django.shortcuts import render # Create your views here. from app.MySer import BookSerializer
from django.views import View
from rest_framework.views import APIView
from rest_framework.response import Response
from app import models class Books(APIView):
def get(self, request, *args, **kwargs):
response = {'status': 100, 'msg': '成功'}
book_list = models.Book.objects.all()
# 第一个参数是要序列化的queryset对象,如果序列化多条,必须指定many=True
# 问?什么情况下many=False,instance=单个对象的时候
book_ser = BookSerializer(book_list, many=True)
print(book_ser.data)
response['books'] = book_ser.data
return Response(response) class Book(APIView):
def get(self,request, id):
response = {'status':100,'msg':'成功'}
book = models.Book.objects.filter(pk=id).first()
book_ser = BookSerializer(book,many=False)
response['book'] = book_ser.data
return Response(response)
-总结:
# 1 变量名和source指定的值不能一样
# 2 source='publish.name'还支持继续 .
# 3 source 还支持方法(没用)
# 4 支持写方法,如下
#方法一定传一个参数,是当前book对象
publish_dic=serializers.SerializerMethodField()
def get_publish_dic(self,obj):
# 猜,这个obj应该是谁,当前book对象
return {'id':obj.publish.pk,'name':obj.publish.name}
补充点:在线格式化json ==> https://www.json.cn/