drf source
# CBV 类型的全是根据反射来的,基于反射实现根据请求方式不同,执行不同的方法
# 原理 :
# a.
url - view() - dispath
class StudentsView(View):
def dispatch(self, request, *args, **kwargs):
func = getattr(self, request.method.lower())
ret = func(request, *args, **kwargs) # 各个函数执行,以及参数 get()....
return ret
def get(self,request):
return HttpResponse('GET')
cbv of running processes
def dispatch(self, request, *args, **kwargs):
ret = super(StudentsView, self).dispatch(request, *args, **kwargs)
return ret
Inheritance: (a plurality of common functionality class, to avoid repetition)
Interview questions
django middleware
- Middleware can write up to several methods: 5
- process_request view response exception
- render_template
Implementation process
What middleware done?
Competence
User login authentication
django csrf_token how to achieve? (interview questions)
In view which: request view request before all
from django.views.decorators.csrf import csrf_exempt
csrf_excmpt exemption request csrf
-
process_view method
Check whether the @csrf_exempt (exempt csrf certification)
To request or obtain token cookie weight
Why is the view, the request is executed after the view to the decorator
CBV little knowledge:
Method ineffective when applied alone csrf
class:...
# @csrf_exempt # 这么加不行
# @method_decorator(csrf_exempt)
def post(self, request):
return HttpResponse('POST')
Which must be added to dispath
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
func = getattr(self, request.method.lower())
ret = func(request, *args, **kwargs) # 各个函数执行,以及参数 get()....
return ret
Or a class on
@method_decorator(csrf_exempt, name='dispatch')
class StudentsView(View):
Write a distpatch method may be less
to sum up:
- Nature: based on the reflection to achieve
- Process: Route view dispatch (reflection)
- csrf_token not canceled from the middleware, to be applied to the class or dispatch csrf_exempt
- Spread
- csrf
- Middleware based proces_view
- Function is provided to the individual decorator or NA
- csrf
restful specification (recommended)
Separating the front and rear end development
A:
http://www.oldboyedu.com/add_user/ user management ....
Many return value, return value, the deal is not good
{
code:666,
}
b:
view
$.ajax({})
#不好, 因为10张表 处理 ,就40条url了
# 规范 : 10个url , 用method来处理不同的
Based fbv write
# 1 根据method不同进行不同的处理
def order(request):
if request.method == "GET":
return HttpResponse('获取')
if request.method == "add":
return HttpResponse('获取')
if request.method == "del":
return HttpResponse('获取')
if request.method == "update":
return HttpResponse('获取')
Based cbv write
class orderView(View):
def get(self,request,*args,**kwargs):
return HttpResponse('获取')
def post(self,request,*args,**kwargs): # 创建
return HttpResponse('获取')
def put(self,request,*args,**kwargs): # 更新
return HttpResponse('获取')
def delete(self,request,*args,**kwargs):
return HttpResponse('获取')
Distinguish 2 domain (cross-domain to solve the problem):
www.luffycity.com
Distinguish api.luffycity.com on subdomains
url way:
www.luffycity.com
www.luffycity.com/api
Way version
www.luffycity.com/api/v1/#
3 Resource Oriented Programming
Everything on the Internet as a resource,
4 Try to use nouns
5 method (5) put on a server update, all update
patch :() partial update
6 filter
www.luffycity.com/api/v1/?status=1
7 status codes
Status codes and code used in conjunction with, the multi-code representation, the front end might be willing to process
8 Back to Results
9 h ... themselves splicing url
Above may not follow, as the case may be,
restful api specifications are what? Talk about your perception of him
Disguised as a veteran, storytelling
In using his time, some adaptation, some do not, there is a problem, and the cross-domain,
Solve: cors
jsonp ..
In the chat, well, then use that
2.djangorestframework framework
pip3 install djangorestframework
Operation may be performed with a token
from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
# 登录认证基于这个类实现
# dispatch->reuqest(封装)->认证(initial)->per():request.user->user->获取认证对象-->类对象--->触发异常或者是token(正常) # 写了一个My的类,写了一个auth_calssess , 有的话就找本类的,没有就去父类里找
class Myauthentication(object):
def authenticate(self,request):
token = request._request.GET.get('token')
if not token:
raise exceptions.AuthenticationFailed('用户认证失败')
return ('alex',None)
def authenticate_header(self,val):
pass
class DogView(APIView):
# authentication_classes = [BaseAuthentication, ] # 获取的是类的对象,
authentication_classes = [Myauthentication, ] # 获取的是类的对象,
# self.dispatch
def get(self, request, *args, **kwargs):
ret = {
'code': 1000,
'msg': 'xxx'
}
return HttpResponse(json.dumps(ret), status=201)
def post(self,request,*args,**kwargs):
return HttpResponse('创建dog')
def put(self,request,*args,**kwargs):
return HttpResponse('更新dog')
def delete(self,request,*args,**kwargs):
return HttpResponse('删除dog')
For this class do serious
dispatch
A. Certification
a. Certification
Source process thoroughly understand: do not understand, add a comment, entrance
dispatch, will not only use, but also to understand the principle
s7129
Today: 1 Certification 2 3 throttle rights (access frequency control) version 4
Use user authentication, you need to write a class, and then write a subject that [,]
It can also be used globally
b. using basic authentication unit
- solve:
- a. Create two tables
- b. User login (return token and saved to the database)
c. Source
authentication_classes = [Authtication,]
# self.dispatch 入口
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 对原生的request进行加工(追加)
# Request(request,parsers=self.get_parsers(), authenticators=self.get_authenticators(), negotiator=self.get_content_negotiator(), parser_context=parser_context)
# request(原生request, [BaseAuthentication对象,], )
# 获取原生request, self._request
# 获取认证类的对象, request.authenticator
# 1.封装Request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
# 2. 认证成功,走反射
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)
def initialize_request(self, request, *args, **kwargs):
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
)
def get_authenticators(self):
# self.authentication_classes = [foo,bar]
return [auth() for auth in self.authentication_classes]
#对象,然后,自己写了这个类,和
as follows:
from rest_framework.authentication import BaseAuthentication
# 重写这两个方法
def authenticate(self, request):
def authenticate_header(self, request): # pass就行
authentication_classes = [Authtication,]
# 用了drf , 对于重用的功能
class Authtication(object):
def authenticate(self,request):
token = request._request.GET.get('token')
token_obj = models.UserToken.objects.filter(token=token).first()
if not token_obj:
raise exceptions.AuthenticationFailed('用户认证失败')
# 在rest_framework内部会将整个两个字段赋值给request,以供后续操作使用
return (token_obj.user, token_obj)
def authenticate_header(self, request):
pass
def initial(self, request, *args, **kwargs):
# 4.实现认证
self.perform_authentication(request)
def perform_authentication(self, request):
request.user
request.user in the Request.py
@property
def user(self):
if not hasattr(self, '_user'):
with wrap_attributeerrors():
# 获取认证对象, 进行一步步的认证
self._authenticate()
return self._user
[BaseAuthentication对象,]
def _authenticate(self):
# [BaseAuthentication对象,]
# 循环认证类的所有对象
for authenticator in self.authenticators:
try:
# 执行认证类的authenticate方法
# 1.如果auth方法抛出异常,self._not_auth()执行
# 2.有返回值,必须得是元祖(request.user, request.auth)
# 3.返回None , 当前不处理,下一个认证来处理
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()
def _not_authenticated(self):
self._authenticator = None
if api_settings.UNAUTHENTICATED_USER:
self.user = api_settings.UNAUTHENTICATED_USER() # AnonymousUser
else:
self.user = None
if api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN() # None
else:
self.auth = None
Executes the function, the function returns
return (token_obj.user, token_obj), according to written here and abnormal neuron progenitor return
d. Code Configuration p = 19
The writing class, returns Ganso certified, return the exception, writes setting in
All classes are then added to the default, not in a single write a
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.auth.FirstAuthtication', 'api.utils.auth.Authtication' ]
}
Global can use, do not use topical
class UserInfoView(APIView):
"""订单相关业务"""
# 类似于中间件, 装饰器的处理restframework的方法,认证登录方法
authentication_classes = []
def get(self, request, *args, **kwargs):
return HttpResponse('用户信息')
http://127.0.0.1:8000/api/v1/order/?token=851c293fe784dea90e079aad5d498f42
{
"code": 1000,
"msg": null,
"data": {
"1": {
"name": "xifu",
"age": 18,
"gender": "男",
"content": "..."
},
"2": {
"name": "xifu2",
"age": 18,
"gender": "男",
"content": "..."
}
}
}
http://127.0.0.1:8000/api/v1/order/
The user is not logged in
In the final, _not_authenticated function
if api_settings.UNAUTHENTICATED_USER:
self.user = api_settings.UNAUTHENTICATED_USER() # AnonymousUser
else:
self.user = None
if api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN() # None
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
def reload_api_settings(*args, **kwargs):
setting = kwargs['setting']
if setting == 'REST_FRAMEWORK':
api_settings.reload()
Therefore, in settings where the use of global settings, USER, and TOKEN
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
REST_FRAMEWORK = {
# 全局使用的认证类
# 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.auth.FirstAuthtication', 'app01.utils.auth.Authtication' ],
'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.auth.FirstAuthtication', ],
"UNAUTHENTICATED_USER": None, # 匿名用户, request.user= None
# 'UNAUTHENTICATED_TOKEN':None , # request.auth = None
}
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
In the settings rest_framework in
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
def reload_api_settings(*args, **kwargs):
setting = kwargs['setting']
if setting == 'REST_FRAMEWORK':
api_settings.reload()
Anonymous is request.user = None
Not modal dialog
Provided by the browser, and then fill out, encryption
Based on django to achieve
Will not use these, are custom realized
e. built-in authentication class
Certification classes must inherit: from rest_framework.authentication import BaseAuthentication
Other certification categories:
Sort:
use
Create a class: method implementation inheritance BaseAuthentication auth ..
return value:
- None, next to perform certification
- Throws exceptions.AuthenticationFailed ( 'User authentication failed') #from rest_framework import exceptions
- (Element 1, element 2) # 1 assigned to the elements of the request.user; element 2 is assigned to request.auth
Topical
class Authtication(object): def authenticate(self,request): token = request._request.GET.get('token') token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed('用户认证失败') # 在rest_framework内部会将整个两个字段赋值给request,以供后续操作使用 return (token_obj.user, token_obj) def authenticate_header(self, request): pass
Global Use
REST_FRAMEWORK = { # 全局使用的认证类 # 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.auth.FirstAuthtication', 'app01.utils.auth.Authtication' ], 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.auth.FirstAuthtication', ], "UNAUTHENTICATED_USER": None, # (没登录) 匿名用户, request.user= None # 返回的是函数()所以写匿名函数 # 'UNAUTHENTICATED_TOKEN':None , # request.auth = None }
2. Source Process
Go first dispatch, request package, and take the initial, find all the objects, execute methods (two) can be set in the setting, but it api.settings Why and settings associated with, do not understand
dispatch
- Package request
Acquiring authentication class definitions (global / local), by the formula to create the object list
initial
- perform_authentication
- request.user (inner loop ...)
- perform_authentication
Things behind and certification process here is the same
II. Permissions
Certification. User_type 1234 when you can have access
Problem: no view can be accessed without permission
Also through the dispatch to 4,
到check_permissions
Question 1 encounter
在设置超级vip时,返回的值是1
if request.user.user_type != 1:
return HttpResponse('无权访回')
AttributeError: 'NoneType' object has no attribute 'user_type'
Because I was set up to give him permission
# 全局使用的认证类
# 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.auth.FirstAuthtication', 'app01.utils.auth.Authtication' ],
'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.auth.FirstAuthtication', ],
Returns empty instead request.user and request.auth, it returns empty
Setting a supervisor vip
According user_type judge each object, and some gave him a super vip, another default does not handle, (where 1 is the vip)
if request.user.user_type != 1:
return HttpResponse('无权访回')
Encapsulated into the class
# 认证过之后就开始权限认证了
class MyPermission(object):
# self.dispatch
def has_permission(self, request, view):
# 把权限写入类里面
if request.user.user_type != 1:
return False
return True # 有权访问
class OrderView(APIView):
# 局部权限
permission_classes = [MyPermission, ]
After all the open global certification, you can not handle auth yet?
class MyPermission1(object):
def has_permission(self, request, view):
# 把权限写入类里面
if request.user.user_type == 3:
return False
return True # 有权访问
class UserInfoView(APIView):
"""订单相关业务(普通用户/vip)"""
# 类似于中间件, 装饰器的处理restframework的方法,认证登录方法
# authentication_classes = []
permission_classes = [MyPermission1, ]
def get(self, request, *args, **kwargs):
return HttpResponse('用户信息')
Completed the basic rights of
Look Source Process
dispatch
initial
check_permissions
# [权限类的对象,权限类的对象,]
for permission in self.get_permissions():
# 通过per...为ture, 则not per..为false,不走, 而为false,则为ture, 走里面,抛异常
if not permission.has_permission(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
)
def permission_denied(self, request, message=None):
"""
If request is not permitted, determine what kind of exception to raise.
"""
if request.authenticators and not request.successful_authenticator:
raise exceptions.NotAuthenticated()
raise exceptions.PermissionDenied(detail=message)
Written global
utils
-auth.py
-permission.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ['app01.utils.permission.SVIPPermission'] # 全局的
}
# 认证过之后就开始权限认证了
class SVIPPermission(object):
# self.dispatch
message = '必须是SVIP才能访问'
def has_permission(self, request, view):
# 把权限写入类里面
if request.user.user_type != 1:
return False
return True # 有权访问
class MyPermission1(object):
def has_permission(self, request, view):
# 把权限写入类里面
if request.user.user_type == 3:
return False
return True # 有权访问
If you write in the global, then all can be used, if you do not use, for a field like
# permission_classes = [MyPermission1, ]
There is no built-in power?
There is a default return true
In order to standardize
from rest_framework.permissions import BasePermission
# 按照代码规范应该继承,内置的
class SVIPPermission(BasePermission):
Other permissions are written by django
Production environment, can not be the default things that are to write their own (custom, but also a higher level)
Sort:
- 1. Restframework written permission of, the best written class, put his assembly
Must inherit: BasePermission, must implement: has_permission method
return value
return False #无权访问 return True #有权访问
Local:
class UserInfoView(APIView): """订单相关业务(普通用户/vip)""" permission_classes = [MyPermission1, ] #加上这个 def get(self, request, *args, **kwargs):
Global:
'DEFAULT_PERMISSION_CLASSES': ['app01.utils.permission.SVIPPermission']
in the afternoon:
2 after landing to see what the user (vip or svip)
3, frequency of visits
Restrictions: for example, one minute how many times 6 times
Accessing a dictionary stored record ID number {=: [12: 10: 10,12: 10: 09,12: 10: 08]}
# 12:10:10,12:10:09,12:10:08,12:10:07,12:10:06,12:10:05
12:50:10
[12: 10: 10,12: 10: 09,12: 10: 08,] clear
12:10:11
[12: 10: 10,12: 10: 09,12: 10: 08] is greater than 3 times, not the
The ip, can be recorded
Access records = {user IP: [....]} // ip but you can change ah, no way, anonymous user, reptiles
Registered users can be restricted, so now the phone number binding, but the user name more, would not be able to do.
class VisitThrottle(object):
def allow_request(self, request, view):
# return True# 可以继续访问 # return False 表示访问频率太高,被限制
return False
def wait(self):
pass
class AuthView(APIView):
authentication_classes = []
permission_classes = []
throttle_classes = [VisitThrottle,]
{
"detail": "Request was throttled."
}