Django之CBV装饰器

昨日内容回顾
django form组件
form组件三大功能
1.渲染标签(渲染仅仅是获取用户输入的input框)
2.校验数据
3.展示信息
from django import forms

	class MyForm(forms.Form):
		name = forms.CharField(max_length=8,
								label='用户名',
								initial='默认值',
								error_messages={
									'max_length':"用户名最大8位",
									'required':'用户名不能为空'
								},
								widget=widgets.TextInput(attrs={'class':'c1 form-control'})
								)
		password = forms.CharField(max_length=8,
									min_length=3,
								label='用户名',
								initial='默认值',
								error_messages={
									'max_length':"密码最大8位",
									'required':'密码不能为空'
									'min_length':'密码最小3位'
								},
								widget=widgets.PasswordInput(attrs={'class':'c1 form-control'})
								))
		email = forms.EmailField(error_messages={
									'invalid':'邮箱格式不正确',
									'required':'邮箱必填'
		})
		
		# 钩子函数
		# 局部钩子
		from django.core.exceptions import ValidationError
		def clean_name(self):
			name = self.cleaned_data.get('name')
			if '666' in name:
				# 1.主动抛出异常
				raise ValidationError("光喊666是不行的")
				# 2.自定义异常
				self.add_error({'name','光喊666是不行的'})
			return name
		# 全局钩子
		def clean(self):
			password = self.cleaned_data.get('password')
			conf_password = self.cleaned_data.get('conf_password')
			if not password == conf_password:
				self.add_error('conf_password','两次密码不一致')
			return self.cleaned_data
		
		
	1.校验数据
		form_obj = MyForm({'name':'jason','password':'123456','email':'[email protected]'})
		# 数据是否合法
		form_obj.is_valid()  # 数据必须全部合法才为True,否则均为False
		# 查看合法的数据
		form_obj.cleaned_data  # 校验通过的数据
		# 查看不合法的数据及其报错原因
		form_obj.errors  # 这是一个大字典,里面放的是所有的不合法字段及其错误信息
	
	2.form渲染标签
		后端先实例化forms对象
			form_obj = MyForm()
		前端三种渲染方式
			1.{{ form_obj.as_p }}
			2.{{form_obj.name.label}}{{form_obj.name}}
			3.{% for foo in form_obj %}
				<p>{{ foo.label }}{{ foo }}</p>
			  {% endfor %}
		
	
	3.展示校验信息
			{% for foo in form_obj %}
				<p>
				{{ foo.label }}{{ foo }}
				<span>{{ foo.errors.0 }}</span>
				</p>
			{% endfor %}
	
	
	
	简单的注册实例
		def register(request):
			form_obj = MyForm()
			if request.method == 'POST':
				form_obj = MyForm(request.POST)
				if form_obj.is_valid():
					models.User.objects.create(**form_obj.cleaned_data)
			return render(request,'register.html',{'form_obj':form_obj})
	
	
	
	
	
	ps:
		1.forms组件中定义的字段某人都是必须添值的(required=True)
		2.label不写默认用的是字段首字母大写
		3.如果提交的信息不合法,input框内的数据会保留
		

django操作cookie与session

	django操作cookie
		django返回的都是HttpResponse对象
		return HttpResponse('ok')
		
		obj = HttpResponse('ok')
		# 设置cookie
		obj.set_cookie('name','jason',max_age=100)			
		return obj
		# 获取
		request.COOKIES.get('name')
		request.COOKIES['name']
		# 删除
		obj.delete_cookie('jason')
		
		
		
	登录实例
		1.没有登录的情况下不能访问其他页面,访问直接跳转到登录页面
		2.装饰器
		3.装饰器内通过target_path = request.get_full_path()获取用户想访问的路径
			给login路径加get参数login?next='%s'%target_path
		4.login视图函数能够通过request.GET.get('next')获取到用户想访问的路径
		
		
	session
		# 设置
		request.session['name'] = 'jason'  # 当你没有创建django需要的默认表的情况下会报错"no such tabel:django_session"
		"""
			1.先生成一个随机字符串
			2.去django_session表中存储数据
				session_key         session_data           date
				随机字符串(加密)     数据(加密)           14天(超时时间)
			3.将生成的随机字符串返回给浏览器,浏览器以cookie存储
				{'sessionid':'随机字符串'}
		"""
		# 获取
		request.session.get('name')
		"""
			1.先获取浏览器传过来的随机字符串
			2.拿着该字符串去django_session表中去比对
			3.将比对到的session_key对应的session_data赋值给request.session
		"""
		# 删除
		request.session.delete()  # 仅仅删除的是数据库的session记录
		request.session.flush()  # 后端数据库及前端浏览器cookie都删
		
		# 设置超时时间
		# 设置会话Session和Cookie的超时时间
		request.session.set_expiry(value)
			* 如果value是个整数,session会在些秒数后失效。
			* 如果value是个datatime或timedelta,session就会在这个时间后失效。
			* 如果value是0,用户关闭浏览器session就会失效。
			* 如果value是None,session会依赖全局session失效策略。

FBV加装饰器

今日内容

CBV加装饰器
# @method_decorator(login_auth,name='get')  # 第二种 name参数必须指定
class MyHome(View):
	@method_decorator(login_auth)  # 第三种  get和post都会被装饰
	def dispatch(self, request, *args, **kwargs):
		super().dispatch(request,*args,**kwargs)
	# @method_decorator(login_auth)  # 第一种
	def get(self,request):
		return HttpResponse('get')

	def post(self,request):
		return HttpResponse('post')
		
django中间件
class SecurityMiddleware(MiddlewareMixin):
	def __init__(self, get_response=None):
		self.sts_seconds = settings.SECURE_HSTS_SECONDS
		self.sts_include_subdomains = settings.SECURE_HSTS_INCLUDE_SUBDOMAINS
		self.sts_preload = settings.SECURE_HSTS_PRELOAD
		self.content_type_nosniff = settings.SECURE_CONTENT_TYPE_NOSNIFF
		self.xss_filter = settings.SECURE_BROWSER_XSS_FILTER
		self.redirect = settings.SECURE_SSL_REDIRECT
		self.redirect_host = settings.SECURE_SSL_HOST
		self.redirect_exempt = [re.compile(r) for r in settings.SECURE_REDIRECT_EXEMPT]
		self.get_response = get_response

	def process_request(self, request):
		path = request.path.lstrip("/")
		if (self.redirect and not request.is_secure() and
				not any(pattern.search(path)
						for pattern in self.redirect_exempt)):
			host = self.redirect_host or request.get_host()
			return HttpResponsePermanentRedirect(
				"https://%s%s" % (host, request.get_full_path())
			)

	def process_response(self, request, response):
    if (self.sts_seconds and request.is_secure() and
            'strict-transport-security' not in response):
        sts_header = "max-age=%s" % self.sts_seconds
        if self.sts_include_subdomains:
            sts_header = sts_header + "; includeSubDomains"
        if self.sts_preload:
            sts_header = sts_header + "; preload"
        response["strict-transport-security"] = sts_header

    if self.content_type_nosniff and 'x-content-type-options' not in response:
        response["x-content-type-options"] = "nosniff"

    if self.xss_filter and 'x-xss-protection' not in response:
        response["x-xss-protection"] = "1; mode=block"

    return response










csrf跨站请求伪造
auth认证模块(用户相关功能)

class SessionMiddleware(MiddlewareMixin):
	def __init__(self, get_response=None):
		self.get_response = get_response
		engine = import_module(settings.SESSION_ENGINE)
		self.SessionStore = engine.SessionStore

	def process_request(self, request):
		session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
		request.session = self.SessionStore(session_key)

	def process_response(self, request, response):
		"""
		If request.session was modified, or if the configuration is to save the
		session every time, save the changes and set a session cookie or delete
		the session cookie if the session has been emptied.
		"""
		try:
			accessed = request.session.accessed
			modified = request.session.modified
			empty = request.session.is_empty()
		except AttributeError:
			pass
		else:
			# First check if we need to delete this cookie.
			# The session should be deleted only if the session is entirely empty
			if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
				response.delete_cookie(
					settings.SESSION_COOKIE_NAME,
					path=settings.SESSION_COOKIE_PATH,
					domain=settings.SESSION_COOKIE_DOMAIN,
				)
			else:
				if accessed:
					patch_vary_headers(response, ('Cookie',))
				if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:
					if request.session.get_expire_at_browser_close():
						max_age = None
						expires = None
					else:
						max_age = request.session.get_expiry_age()
						expires_time = time.time() + max_age
						expires = cookie_date(expires_time)
					# Save the session data and refresh the client cookie.
					# Skip session save for 500 responses, refs #3881.
					if response.status_code != 500:
						try:
							request.session.save()
						except UpdateError:
							raise SuspiciousOperation(
								"The request's session was deleted before the "
								"request completed. The user may have logged "
								"out in a concurrent request, for example."
							)
						response.set_cookie(
							settings.SESSION_COOKIE_NAME,
							request.session.session_key, max_age=max_age,
							expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
							path=settings.SESSION_COOKIE_PATH,
							secure=settings.SESSION_COOKIE_SECURE or None,
							httponly=settings.SESSION_COOKIE_HTTPONLY or None,
						)
		return response
	
class CsrfViewMiddleware(MiddlewareMixin):
	def process_request(self, request):
		csrf_token = self._get_token(request)
		if csrf_token is not None:
			# Use same token next time.
			request.META['CSRF_COOKIE'] = csrf_token

	def process_view(self, request, callback, callback_args, callback_kwargs):
		if getattr(request, 'csrf_processing_done', False):
			return None

		# Wait until request.META["CSRF_COOKIE"] has been manipulated before
		# bailing out, so that get_token still works
		if getattr(callback, 'csrf_exempt', False):
			return None

		# Assume that anything not defined as 'safe' by RFC7231 needs protection
		if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
			if getattr(request, '_dont_enforce_csrf_checks', False):
				# Mechanism to turn off CSRF checks for test suite.
				# It comes after the creation of CSRF cookies, so that
				# everything else continues to work exactly the same
				# (e.g. cookies are sent, etc.), but before any
				# branches that call reject().
				return self._accept(request)

			if request.is_secure():
				# Suppose user visits http://example.com/
				# An active network attacker (man-in-the-middle, MITM) sends a
				# POST form that targets https://example.com/detonate-bomb/ and
				# submits it via JavaScript.
				#
				# The attacker will need to provide a CSRF cookie and token, but
				# that's no problem for a MITM and the session-independent
				# secret we're using. So the MITM can circumvent the CSRF
				# protection. This is true for any HTTP connection, but anyone
				# using HTTPS expects better! For this reason, for
				# https://example.com/ we need additional protection that treats
				# http://example.com/ as completely untrusted. Under HTTPS,
				# Barth et al. found that the Referer header is missing for
				# same-domain requests in only about 0.2% of cases or less, so
				# we can use strict Referer checking.
				referer = force_text(
					request.META.get('HTTP_REFERER'),
					strings_only=True,
					errors='replace'
				)
				if referer is None:
					return self._reject(request, REASON_NO_REFERER)

				referer = urlparse(referer)

				# Make sure we have a valid URL for Referer.
				if '' in (referer.scheme, referer.netloc):
					return self._reject(request, REASON_MALFORMED_REFERER)

				# Ensure that our Referer is also secure.
				if referer.scheme != 'https':
					return self._reject(request, REASON_INSECURE_REFERER)

				# If there isn't a CSRF_COOKIE_DOMAIN, require an exact match
				# match on host:port. If not, obey the cookie rules (or those
				# for the session cookie, if CSRF_USE_SESSIONS).
				good_referer = (
					settings.SESSION_COOKIE_DOMAIN
					if settings.CSRF_USE_SESSIONS
					else settings.CSRF_COOKIE_DOMAIN
				)
				if good_referer is not None:
					server_port = request.get_port()
					if server_port not in ('443', '80'):
						good_referer = '%s:%s' % (good_referer, server_port)
				else:
					# request.get_host() includes the port.
					good_referer = request.get_host()

				# Here we generate a list of all acceptable HTTP referers,
				# including the current host since that has been validated
				# upstream.
				good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
				good_hosts.append(good_referer)

				if not any(is_same_domain(referer.netloc, host) for host in good_hosts):
					reason = REASON_BAD_REFERER % referer.geturl()
					return self._reject(request, reason)

			csrf_token = request.META.get('CSRF_COOKIE')
			if csrf_token is None:
				# No CSRF cookie. For POST requests, we insist on a CSRF cookie,
				# and in this way we can avoid all CSRF attacks, including login
				# CSRF.
				return self._reject(request, REASON_NO_CSRF_COOKIE)

			# Check non-cookie token for match.
			request_csrf_token = ""
			if request.method == "POST":
				try:
					request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
				except IOError:
					# Handle a broken connection before we've completed reading
					# the POST data. process_view shouldn't raise any
					# exceptions, so we'll ignore and serve the user a 403
					# (assuming they're still listening, which they probably
					# aren't because of the error).
					pass

			if request_csrf_token == "":
				# Fall back to X-CSRFToken, to make things easier for AJAX,
				# and possible for PUT/DELETE.
				request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')

			request_csrf_token = _sanitize_token(request_csrf_token)
			if not _compare_salted_tokens(request_csrf_token, csrf_token):
				return self._reject(request, REASON_BAD_TOKEN)

		return self._accept(request)

	def process_response(self, request, response):
		if not getattr(request, 'csrf_cookie_needs_reset', False):
			if getattr(response, 'csrf_cookie_set', False):
				return response

		if not request.META.get("CSRF_COOKIE_USED", False):
			return response

		# Set the CSRF cookie even if it's already set, so we renew
		# the expiry timer.
		self._set_token(request, response)
		response.csrf_cookie_set = True
		return response

django默认有七个中间件,但是django暴露给用户可以自定义中间件并且里面可以写五种方法
ps:

1.请求来的时候会依次执行每一个中间件里面的process_request方法(如果没有直接通过)
2.响应走的时候会依次执行每一个中间件里面的process_response方法(如果没有直接通过)

django中间件能够帮我实现 网站全局的身份验证,黑名单,白名单,访问频率限制,反爬相关
》》》:django用来帮你全局相关的功能校验

自定义中间件
新建一个任意名字的文件夹,里面新建一个任意名字py文件
from django.utils.deprecation import MiddlewareMixin

总结:
	需要你掌握的:
	process_request:请求来的时候从上往下依次执行每一个中间件里面的process_request
	process_response :响应走的时候会从下往上依次执行每一个中间件里面的process_response方法
						
	了解:
	process_view:路由匹配成功执行视图之前自动触发(从上往下依次执行)
	process_exception:当视图函数报错了,自动触发(从下往上依次执行)
	process_template_response:视图函数返回的对象有一个render()方法
						(或者表明该对象是一个TemplateResponse对象或等价方法)(从下往上依次执行)

csrf跨站请求伪造

form表单中如何跨站请求伪造
{% csrf_token %}
<input type="hidden" name="csrfmiddlewaretoken" value="2vzoo1lmSWgLTdI2rBQ4PTptJQKRQTRwnqeWRGcpdAQGagRp8yKg8RX2PdkF4aqh">
ps:value是动态生成的,每一次刷新都不一样



from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_exempt  # 不校验csrf
def index1(request):
	return HttpResponse('ok')

@csrf_protect  # 校验csrf
def index2(request):
	return HttpResponse('ok')


csrf装饰CBV需要注意(******)
csrf_protect 跟正常的CBV装饰器一样      三种
csrf_exempt  只能有下面两种方式
		@method_decorator(csrf_exempt,name='dispatch')  # 第一种 
		class Index3(View):
			# @method_decorator(csrf_exempt)   # 第二种  
			def dispatch(self, request, *args, **kwargs):
				super().dispatch(request,*args,**kwargs)  
		其实都是给dispatch加

Auth模块
用户功能模块

命令行创建超级用户
	createsuperuser


# 局部配置
# @login_required(login_url='/auth_login/')  
# 全局配置 
# auth自动跳转
LOGIN_URL = '/auth_login/'  # settings.py配置


# AUTH_USER_MODEL = "app名.models里面对应的模型表名"
AUTH_USER_MODEL = 'app01.Userinfo'

class Userinfo(AbstractUser):
	phone = models.CharField(max_length=32)
	avatar = models.CharField(max_length=32)
# 用自己创建的表,所有auth模块的方法使用方式不变

猜你喜欢

转载自blog.csdn.net/weixin_43183295/article/details/92799396