西游之路——python全栈——Django模块简便使用
目录
一:登录操作
1.简单使用:
注意:使用@login_required需要我们配置
2.方法了解
二:csrf的多种使用方法
1.需求分析
2.实现代码
三:import导入的多种方法(用于反射)
1.一般导入模块直接使用import
2.需求:现有字符串代表各个模块,如何通过反射获取该模块
一:登录操作
from django.contrib.auth import authenticate,login,logout #可以用来做登录验证
from django.contrib.auth.decorators import login_required #装饰器,用于对用户是否登录进行验证
1.简单使用:
def acc_login(request): error_msg = '' if request.method == "POST": username = request.POST.get("username") password = request.POST.get("password") user = authenticate(username=username,password=password) #进行用户验证 if user: login(request,user) #登录状态,添加入session, request.user = user return redirect(request.GET.get("next","/")) else: error_msg = "Wrong Username Or Password" return render(request,"login.html",{"error_msg":error_msg}) def acc_logout(request): logout(request) #清除session数据 return redirect("/login.html") from django.contrib.auth.decorators import login_required @login_required def dashboard(request): return render(request,"Sale/dashboard.html")
注意:使用@login_required需要我们配置
LOGIN_URL = "/login.html" #默认是在accounts/login路由下跳转
2.方法了解
(1)authenticate方法
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None: username = kwargs.get(UserModel.USERNAME_FIELD) try: user = UserModel._default_manager.get_by_natural_key(username) #根据用户名获取用户对象 except UserModel.DoesNotExist: # Run the default password hasher once to reduce the timing # difference between an existing and a non-existing user (#20760). UserModel().set_password(password) else: if user.check_password(password) and self.user_can_authenticate(user): #根据密码进行登录验证,以及获取用户的操作权限 return user
UserModel = get_user_model()
def get_user_model(): #返回用户表对象,对象由AUTH_USER_MODEL指定,默认是auth.User默认数据表,我们可以在自己的setting文件中进行覆盖 """ Returns the User model that is active in this project. """ return django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False)
(2)login方法
def login(request, user, backend=None):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def login(request, user, backend=None): 2 """ 3 Persist a user id and a backend in the request. This way a user doesn't 4 have to reauthenticate on every request. Note that data set during 5 the anonymous session is retained when the user logs in. 6 """ 7 session_auth_hash = '' 8 if user is None: 9 user = request.user 10 if hasattr(user, 'get_session_auth_hash'): 11 session_auth_hash = user.get_session_auth_hash() 12 13 if SESSION_KEY in request.session: 14 if _get_user_session_key(request) != user.pk or ( 15 session_auth_hash and 16 not constant_time_compare(request.session.get(HASH_SESSION_KEY, ''), session_auth_hash)): 17 # To avoid reusing another user's session, create a new, empty 18 # session if the existing session corresponds to a different 19 # authenticated user. 20 request.session.flush() 21 else: 22 request.session.cycle_key() 23 24 try: 25 backend = backend or user.backend 26 except AttributeError: 27 backends = _get_backends(return_tuples=True) 28 if len(backends) == 1: 29 _, backend = backends[0] 30 else: 31 raise ValueError( 32 'You have multiple authentication backends configured and ' 33 'therefore must provide the `backend` argument or set the ' 34 '`backend` attribute on the user.' 35 ) 36 37 request.session[SESSION_KEY] = user._meta.pk.value_to_string(user) 38 request.session[BACKEND_SESSION_KEY] = backend 39 request.session[HASH_SESSION_KEY] = session_auth_hash 40 if hasattr(request, 'user'): 41 request.user = user 42 rotate_token(request) 43 user_logged_in.send(sender=user.__class__, request=request, user=user) 44 45 设置session,向request中添加user属性,可以直接使用request.user获取User表对象
(3)logout方法
def logout(request):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def logout(request): 2 """ 3 Removes the authenticated user's ID from the request and flushes their 4 session data. 5 """ 6 # Dispatch the signal before the user is logged out so the receivers have a 7 # chance to find out *who* logged out. 8 user = getattr(request, 'user', None) 9 if hasattr(user, 'is_authenticated') and not user.is_authenticated: 10 user = None 11 user_logged_out.send(sender=user.__class__, request=request, user=user) 12 13 # remember language choice saved to session 14 language = request.session.get(LANGUAGE_SESSION_KEY) 15 16 request.session.flush() 17 18 if language is not None: 19 request.session[LANGUAGE_SESSION_KEY] = language 20 21 if hasattr(request, 'user'): 22 from django.contrib.auth.models import AnonymousUser 23 request.user = AnonymousUser() 24 25 清空session,删除request.user
(4)login_required方法
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):#function是我们装饰的函数名,redirect_field_name是跳转时所带的参数,默认next
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 """ 2 Decorator for views that checks that the user is logged in, redirecting 3 to the log-in page if necessary. 4 """ 5 actual_decorator = user_passes_test( 6 lambda u: u.is_authenticated, 7 login_url=login_url, 8 redirect_field_name=redirect_field_name 9 ) 10 if function: 11 return actual_decorator(function) 12 return actual_decorator
============
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): 2 """ 3 Decorator for views that checks that the user passes the given test, 4 redirecting to the log-in page if necessary. The test should be a callable 5 that takes the user object and returns True if the user passes. 6 """ 7 8 def decorator(view_func): 9 @wraps(view_func, assigned=available_attrs(view_func)) 10 def _wrapped_view(request, *args, **kwargs): 11 if test_func(request.user): 12 return view_func(request, *args, **kwargs) 13 path = request.build_absolute_uri() 14 resolved_login_url = resolve_url(login_url or settings.LOGIN_URL) 15 # If the login url is the same scheme and net location then just 16 # use the path as the "next" url. 17 login_scheme, login_netloc = urlparse(resolved_login_url)[:2] 18 current_scheme, current_netloc = urlparse(path)[:2] 19 if ((not login_scheme or login_scheme == current_scheme) and 20 (not login_netloc or login_netloc == current_netloc)): 21 path = request.get_full_path() 22 from django.contrib.auth.views import redirect_to_login 23 return redirect_to_login( 24 path, resolved_login_url, redirect_field_name) 25 return _wrapped_view 26 return decorator 27 28 装饰器方法
二:csrf的多种使用方法
from django.views.decorators.csrf import csrf_exempt
1.需求分析
当我们需要对某一个view方法去掉csrf_token验证时。总不至于去注释掉所有的csrf验证吧
# 'django.middleware.csrf.CsrfViewMiddleware',
那么我们需要去取消某一个方法的csrf验证
2.实现代码
1.FBV:直接使用装饰器方法
@csrf_exempt def asset(request): pass
2.CBV:需要再去引入一个模块(其实也可以直接使用)
from django.utils.decorators import method_decorator
class AssetView(View): @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): return super(AssetView, self).dispatch(request, *args, **kwargs)
def post(self,request,*args,**kwargs):
pass
def put(self,request,*args,**kwargs):
pass
其中dispatch()方法:作用是将任务分发到正确的方法上。因为需要过滤掉csrf的方法不止post,还有put等,所以在dispatch中过滤掉csrf,那么在其他的方法上可以不用去管
3.在url中进行过滤
from django.conf.urls import url from API import views as v1 from django.views.decorators.csrf import csrf_exempt urlpatterns = [ url(r'^asset',csrf_exempt(v1.AssetView.as_view())), ]
三:import导入的多种方法(用于反射)
1.一般导入模块直接使用import
import 模块 #一般我们是直接使用import导入对应模块
from 包 import 模块 #多层导入
2.需求:现有字符串代表各个模块,如何通过反射获取该模块
(1)使用__import__
__import__("模块")
__import__("层一.层二.层三.模块",fromlist=True) #对于多层,我们使用.连接。注意:fromlist需要添加为True,不然只会导入层一,调用的使用我们还要一级一级向下找,不方便
def __import__(name, globals=None, locals=None, fromlist=(), level=0): # real signature unknown; restored from __doc__
When importing a module from a package, note that __import__('A.B', ...)
returns package A when fromlist is empty, but its submodule B when
fromlist is not empty.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package:test3 ---> 包下面有t2.py文件,定义test2方法 2 无fromlist: 3 md = __import__("test3.t2") 4 md.t2.test2() #test2 5 6 7 有fromlist 8 md = __import__("test3.t2",fromlist=True) 9 md.test2() 10 11 演示结果
(2)使用importlib.
import_module
def import_module(name, package=None): #如果是相对导入的话,第二个参数是需要的 The 'package' argument is required when performing a relative import. It specifies the package to use as the anchor point from which to resolve the relative import to an absolute import.
md = importlib.import_module("test3.t2") md.test2() #test2
md = importlib.import_module(".t2","test3") #.t2代表时相对于test3下的相对路径,就是相当于将前后连接test3.t2 md.test2()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 md = importlib.import_module("test3.t1.t11") 2 md.test11() 3 4 md = importlib.import_module(".t1.t11","test3") 5 md.test11() 6 7 #test11 8 #test11 9 10 再多一级