django实现登录认证,上传图片,中间件和分页
登录认证
-
创建cookies
-
set_cookies(key, value, max_age=10)
-
max_age 存活时间
-
-
加载static
-
第一种方法:
-
{% load static %}
-
{% static ‘’ %}
-
第二种:
-
/static/xxx.css
-
3.删除cookie
- delete_cookie(key)
import random
import time
from django.contrib.auth.hashers import make_password, check_password
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
# Create your views here.
from uauth.models import Users
def regist(request):
if request.method == 'GET':
return render(request, 'register.html')
if request.method == 'POST':
# 注册
name = request.POST.get('name')
password = request.POST.get('password')
# 加密
password = make_password(password)
Users.objects.create(
u_name=name,
u_password=password
)
return HttpResponseRedirect('/uauth/login/')
def login(request):
if request.method == 'GET':
return render(request, 'day6_login.html')
if request.method == 'POST':
# 如果登录成功,绑定参数到cookie中,set_cookie
name = request.POST.get('name')
password = request.POST.get('password')
if Users.objects.filter(u_name=name).exists():
user = Users.objects.get(u_name=name)
if check_password(password, user.u_password):
s = 'qwertyuiopasdfghjklzxcvbnm1234567890'
ticket = ''
for i in range(15):
# 获取随机的字符串
ticket += random.choice(s)
now_time = int(time.time())
ticket = 'TK_' + ticket + str(now_time)
# ticket = 'jkdjasfkn'
# 绑定令牌到cookie里面
# response = HttpResponse('登录成功')
# 登录成功之后跳转
response = HttpResponseRedirect('/stu/index/')
# max_age 存活时间 单位是秒
response.set_cookie('ticket', ticket, max_age=30000)
# 存在服务端
user.u_ticket = ticket
user.save()
return response
else:
# 密码错误情况
return render(request, 'day6_login.html', {'password': '用户密码错误'})
else:
# return HttpResponse('用户不存在')
return render(request, 'day6_login.html', {'name': '用户不存在'})
def logout(request):
if request.method == 'GET':
response = HttpResponseRedirect('/uauth/login/')
response.delete_cookie('ticket')
return response
上传图片
- settings.py中设置media,为上传的文件设置存储路径
- 在主目录下添加media文件夹
- 在media文件夹下添加upload文件夹
- 在models.py文件中添加字段
- 在当前环境中加载 Pillow 这个包 pip install Pillow
- ImageField 方法里面会自动调用Pillow这个库,并且调用的这个库的名字是Pli
- 在HTML页面表单中
- 页面form中加enctype=“multipart/form-data”
- 添加type=file 标签
- 在主项目中主urls.py文件中
- 将media文件夹变成静态文件
- 在views.py文件中
- 获取文件的方法是request.FILES.get(’’)
# settings.py
# 配置上传文件
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# models.py文件
class StudentInfo(models.Model):
i_addr = models.CharField(max_length=30)
# 使用ImageField需要先pip install Pillow这个包,方法里面会自动导入,导入的名字是Pli
i_image = models.ImageField(upload_to='upload', null=True)
s = models.OneToOneField(Student)
- 在HTML文件中
<form action="{% url 'stu:addStuInfo' stu_id %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{# <input type="hidden" value="{{ stu_id }}" name="stu_id">#}
地址: <input type="text" name="addr">
头像: <input type="file" name="img">
<input type="submit" value="提交">
</form>
# 在主项目中主urls.py文件中
from django.conf.urls import url, include
from django.contrib import admin
from django.contrib.staticfiles.urls import static # new
from day5 import settings # new
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^stu/', include('stu.urls', namespace='stu')),
url(r'^uauth/',include('uauth.urls', namespace='uauth'))
]
# 将media文件变成静态文件
urlpatterns += static(settings.MEDIA_URL, document_root= settings.MEDIA_ROOT)
中间件
-
面向切面编码 AOP
- process_request: 在处理url路由之前进行处理逻辑
- process_response: 在响应返回浏览器之前调用
- process_view:调用视图之前执行
- process_templates_resposne:在视图刚好执行完的时候调用
-
埋点
- SEO url点击率
- ‘django.middleware.csrf.CsrfViewMiddleware’
- django中定义好的中间件, 这要求我们传post请求时需要在form表单中加上{% csrf_token %}。
- 否则django后台将会拒绝我们的post请求
process_request
- 在主项目目录下创建utils文件夹
- 在里面创建文件__init__.py 和 UserAuthMiddleware.py(这个文件名可以自己定)
- 在UserAuthMiddleware.py文件中编写要执行的业务逻辑,这里我们要验证request中是否有ticken
- settings.py 中MIDDLEWARE = []添加自己写的中间件
# settings.py 文件中
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'utils.UserAuthMiddleware.AuthMiddleware', # 添加自己定义的中间键
]
# UserAuthMiddleware.py文件中
from django.http import HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin # 注意导入的路径
from uauth.models import Users
# 继承MiddlewareMixin
class AuthMiddleware(MiddlewareMixin):
# 方法名不能写错,相当于重写这个方法, 需要传参数
def process_request(self, request):
# 统一验证登录
# return None 或者不写return直接向下执行
if request.path == '/uauth/login/' or request.path == '/uauth/regist/':
return None
ticket = request.COOKIES.get('ticket')
if not ticket:
return HttpResponseRedirect('/uauth/login/')
users = Users.objects.filter(u_ticket=ticket)
if not users:
return HttpResponseRedirect('/uauth/login/')
# 为request请求绑定user,以便可以在各个页面中访问user
request.user = users[0]
分页
-
在views中,查询到要显示在网页上的数据
-
实例化Paginator
-
并制定分页标准
-
Paginator对象
- page(number): 返回number页的数据
- count() 统计总共有多少条记录
- num_pages:多少页
- page_range:将所有页码放在一个列表中,可以通过遍历提取出来[1,2,3]
-
page对象
-
has_next: 是否有下一页
-
next_page_number: 下一页
-
has_previous: 是否有上一页
-
previous_page_number: 上一页
-
number:当前页数
-
# views.py文件中
def aStuPage(request):
if request.method == 'GET':
# 如果前面的值为空,默认为后面的1
page_id = request.GET.get('page_id', 1)
stus = Student.objects.all()
# 表示stus的数据以3个为一页
paginator = Paginator(stus, 3)
# 当前的页里面的数据,可遍历
page = paginator.page(int(page_id))
return render(request, 'index_page.html', {'stus': page})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>所有学生页面</title>
</head>
<body>
{% for stu in stus %}
姓名:{{ stu.s_name }}
电话:{{ stu.s_tel }}
地址:{{ stu.studentinfo.i_addr }}
{% if stu.studentinfo.i_image %}
头像:<img src="/media/{{ stu.studentinfo.i_image }}" width="120" height="180">
{% endif %}
<br />
{% endfor %}
<!--num_pages:计算共有多少页,count() 统计总共有多少条记录-->
<h4>一共{{ stus.paginator.num_pages }}页/一共{{ stus.paginator.count }}条</h4>
<h5>
<!--page_range:将所有页码放在一个列表中,可以通过遍历提取出来-->
{% for i in stus.paginator.page_range %}
<!--传递页数-->
<a href="/stu/astupage/?page_id={{ i }}">{{ i }}</a>
{% endfor %}
</h5>
<!-- 判断前面是否有页-->
{% if stus.has_previous %}
<a href="/stu/astupage/?page_id={{ stus.previous_page_number }}">上一页</a>
{% endif %}
当前第{{ stus.number }}页
{% if stus.has_next %}
<a href="/stu/astupage/?page_id={{ stus.next_page_number }}">下一页</a>
{% endif %}
<h4>--------------我是分割线-------------</h4>
<a href="{% url 'stu:addStu' %}">添加学生</a>
</body>
</html>