昨日内容回顾
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模块的方法使用方式不变