1装饰器(闭包)
装饰器三特征
1.外层函数内嵌内层函数
2.外层函数返回内层函数
3.内层函数调用外层函数的参数
不用装饰器时的hindex方法
def hindex(request):
if request.method == 'GET':
if request.session.get('user_id'): #判断user_id存在不
user_id = request.session['user_id']
user = User.objects.get(pk=user_id)
print('当前登陆系统的人为:%s' % user.username)
return render(request, 'index.html')
else:
return render(request, 'login.html')
用装饰器实现上述方法
def is_login(func):
def check_status(request):
if request.session.get('user_id'):
return func(request) #相当于my_index函数
else:
return HttpResponseRedirect(reverse('user:login'))
return check_status
装饰器实现hindex函数的方法
@is_login
def my_hindex(request):
if request.method == 'GET':
return render(request, 'index.html')
2中间件
2.1中间件基本概率
中间件的作用就是:面向切面编程AOP,在httpRequest请求还没到的view之前,与view返回的httpResponse还未发送给请求者之前,对httpRequest与httpResponse做出修改。
Django的setting文件中有一个MIDDLEWARE_CLASSES列表专门放置中间件;只要把中间件放入MIDDLEWARE_CLASSES中就可以使用。
中间件有process_request(用户发起访问请求到匹配路由之间)、process_view(匹配路由到业务之间)、process_template_response(业务到html模板之间)、process_exception(异常捕获:业务到模型至模板之间)及process_response(模板到用户看到的渲染页面之间)五种;
其中process_request、process_view及process_response三种经常用到;
五个中间件函数:
1.process_request(self,request):在匹配路由之前被调用;
在process_request不要写return http对象(否则其他中间件不再被执行),但可以写return None表示不在执行本中间件以下内容,直接跳出process_request方法
2.process_view(self,request,view_func,view_args,view_kwargs):在执行视图函数之前被调用
3.process_response(self,request,response):在视图函数响应之后被调用
4.process_template_response():默认不会被主动调用
5.process_exception():默认不会被主动调用,当出现异常时,才会被触发
中间件执行顺序,先执行process_request,再执行视图函数(views),最后执行process_response
有多个中间件的时候的执行顺序,先按定义顺序将所有process_request执行完,再执行视图函数(views),最后逆序执行所有process_response
执行process_request从上到下执行,执行process_view从上到下执行;剩下三个都是从下到上执行
process_request函数中不能写return内容,写了将会在此结束只执行process_request和process_response
2.2中间件函数的基本参数及示例
from user.models import User
class TestMiddlware1(MiddlewareMixin):
def process_request(self, request):
print('test1 process request')
对所有的请求都进行登陆状态的校验
path = request.path
if path in ['/user/register/', '/user/login/', '/user/my_login/']:
跳过以下所有代码,直接访问路由对应的视图函数
return None
try:
user_id = request.session['user_id']
user = User.objects.get(pk=user_id)
request.user = user
return None
except Exception as e:
return HttpResponseRedirect(reverse('user:my_login'))
def process_view(self, request, view_func, view_args, view_kwargs):
print('test1 view')
def process_response(self, request, response):
print('test1 process response')
return response
class TestMiddlware2(MiddlewareMixin):
def process_request(self, request):
print('test2 process request')
def process_view(self, request, view_func, view_args, view_kwargs):
print('test2 view')
def process_response(self, request, response):
print('test2 process response')
return response
#test1 process request、test2 process request、test1 view
#test2 view、test2 process response、test1 process response
3分页
分页可以有两种方法;切片和用paginator库
切片主要是先查询出要查看的内容的所有信息,然后对信息进行按要查看的页进行切片
3.1切片分页
page = int(request.GET.get('page', 1));获取要查看的页码
stus = Student.objects.all()[((page-1)3):(page3)];获得要查看的页的信息
def all_stu(request):
if request.method == 'GET':
获取分页的角码
pag = int(request.GET.get('page', 1))
第一种方式:使用切片实现分页
stus = Student.objects.all()[((pag-1)*3):(pag*3)]
return render(request, 'stus.html', {'stus': stus})
3.2paginator库分页
pg=Paginator(总数据,一页显示信息数)
取某一页信息:pg.page(某页)
page_range:页码
has_previous:是否有上一页
has_next:是否有下一页
previous_page_number:上一页的页码
paginator.page(所获取具体某页的页数)
stus.has_previous 判断stus中当前页面是否存在上一页,返回布尔值
stus.has_next 判断stus中当前页面是否存在下一页,返回布尔值
stus.previous_page_number获取stus中当前页面中的上一页的页码,返回int值
stus.number:获取当前页页码
stus.paginator.num_pages:获取共多少页
def all_stu(request):
if request.method == 'GET':
获取分页的角码
pag = int(request.GET.get('page', 1))
第二种方式:使用Paginator库实现分页
stus = Student.objects.all()
pg = Paginator(stus, 3)
my_stu = pg.page(pag)
return render(request, 'stus.html', {'stus': my_stu})
html中代码
在html文件中跳转至另一个路由:/app/add_stu/
<a href="{% url 'app:add_stu' %}">添加学生信息</a>
{% extends 'base_main.html' %}
{% block content %}
<p><a href="{% url 'app:add_stu' %}">添加学生信息</a></p>
<table>
<thead>
<th>编号:</th>
<th>姓名:</th>
<th>年龄:</th>
<th>性别:</th>
<th>头像:</th>
</thead>
<tbody>
{% for stu in stus %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ stu.s_name }}</td>
<td>{{ stu.s_age }}</td>
<td>{% if stu.s_gender %}
男
{% else %}
女
{% endif %}
</td>
<td><img src="/media/{{ stu.icon }}"></td>
</tr>
{% endfor %}
</tbody>
</table>
<p>
当前第{{ stus.number }}页,共{{ stus.paginator.num_pages }}页
{% if stus.has_previous %}
<a href="{% url 'app:all_stu' %}?page={{ stus.previous_page_number }}">上一页</a>
{% endif %}
{# 分页并标记页码进行跳转#}
{% for i in stus.paginator.page_range %}
{# <a href="/app/all_stu/?page={{ i }}">{{ i }}</a>#}
<a href="{% url 'app:all_stu' %}?page={{ i }}">{{ i }}</a>
{% endfor %}
{% if stus.has_next %}
<a href="{% url 'app:all_stu' %}?page={{ stus.next_page_number }}">下一页</a>
{% endif %}
</p>
{% for stu in stus %}
{% endfor %}
{% endblock %}
4文件上传
文件上传需要先安装Pillow(执行pip install Pillow)
文件上传中,需要在前端的form表单中添加enctype="multipart/form-data"参数
后端获取上传的图片等文件:request.FILES.get(key)或requests.FILES['key']
在模型中新加字段:ImageField(upload_to='upload')
模板中解析:<img src='/media/{{ stu.icon }}'
4.1文件上传的配置
settings中最后配置访问media目录
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
django工程文件下路由文件中的最后配置
from django.contrib.staticfiles.urls import static
urlpatterns += static(MEDIA_URL, document_root=MEDIA_ROOT)
class Student(models.Model):
icon = models.ImageField(upload_to='upload', null=True)
添加了新的字段后,不要再次迁移,而是到数据库的查询文件中新添加一列
alter table student add icon varchar(100) null;数据库中给表添加一列
输入姓名和上传图片
{% extends 'base_main.html' %}
{% block content %}
<form action="" method="post" enctype="multipart/form-data">
<p>姓名:<input type="text" name="username"></p>
<p>图片:<input type="file" name="icon"></p>
<p><input type="submit" value="提交"></p>
</form>
{% endblock %}
新建用户保存上传文件及姓名
def add_stu(request):
if request.method == 'GET':
return render(request, 'add_stu.html')
if request.method == 'POST':
# 1.获取数据
username = request.POST.get('username')
icon = request.FILES.get('icon')
# 2. 保存
Student.objects.create(s_name=username, icon=icon)
# 3. 跳转到列表页面
return HttpResponseRedirect(reverse('app:all_stu'))
查看文件代码见3.2代码块中
网友评论