美文网首页
day47-中间件、分页及文件上传

day47-中间件、分页及文件上传

作者: barriers | 来源:发表于2019-01-09 23:49 被阅读0次

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代码块中

相关文章

网友评论

      本文标题:day47-中间件、分页及文件上传

      本文链接:https://www.haomeiwen.com/subject/tmenrqtx.html