龙空技术网

项目实战Django Web开发进阶-10-登录验证,导航,分页

逸剑听潮 75

前言:

现时各位老铁们对“页面导航分页算法有哪些”大致比较关切,朋友们都需要分析一些“页面导航分页算法有哪些”的相关文章。那么小编同时在网摘上收集了一些关于“页面导航分页算法有哪些””的相关内容,希望小伙伴们能喜欢,大家一起来了解一下吧!

登录验证

登陆验证的方法有多种,可以利用 django 提供的@login_required,或者中间件,或者 session,或者 cookie。因为本教程中没有使用 django 自带的登陆方式进行登录,所以最好自己实现登陆验证,这里就采用了最简单的方式 cookie 进行验证登录。

首先需要存储 cookie。当登录成功后将 ticket 和 username,存储到 cookie 中。打开 users/views.py,进行修改:

# 登录def login(request):    if request.method == 'GET':        return render(request, 'users/login.html')    if request.method == 'POST':        # 如果登录成功,转到 order 页面        username = request.POST.get('username')        password = request.POST.get('password')                # 查询用户是否在数据库中        if User.objects.filter(username=username).exists():            user = User.objects.get(username=username)            if password == user.password:                ticket = time = datetime.datetime.now().strftime('%Y%m%d%H%M%S%f')                   response = HttpResponseRedirect('/orders/')     #转到 order 页面                #max_age 存活时间(秒)                response.set_cookie('ticket', ticket, max_age=10000)                response.set_cookie('username', username, max_age=10000)                # 存在服务端                user.ticket = ticket                user.save() #保存                #response.user = user                return response            else:                return render(request, 'users/login.html', {'error': '用户密码错误'})        else:            return render(request, 'users/login.html', {'error': '用户不存在'})

点击退出时,需要清除 cookie。在 users/views.py 中:

# 退出def logout(request):    request.session.clear()    #清除 session    response = HttpResponseRedirect('/users/login/')    response.delete_cookie("username")  #清除 coolie    response.delete_cookie('ticket')    return response

在需要验证的功能上进行验证登陆,如果还没有登陆就转向登陆页面。例如点餐列表页面,就需要登录之后才能查看,打开 orders/views.py,增加如下代码:

def order(request):    ticket = request.COOKIES.get('ticket')    if not ticket:        return HttpResponseRedirect('/users/login/')     user = User.objects.filter(ticket=ticket)    if not user:        return HttpResponseRedirect('/users/login/')     ... ...

凡是需要验证登录的功能,都可以这样进行验证。

添加导航链接

目前在导航栏上的文字,还没有添加链接。在公共 templates/base.html 中修改导航栏部分的代码。默认只显示登录和注册链接:

<div class="nevbar">            <div class="flow-left"><img src="{% static 'img/order.jpg' %}" width="32px" title="点餐"></div>            {% block nevbar %}            <div class="flow-right"><a href="{% url 'users:regist' %}">注册</a></div>            <div class="flow-right"><a href="{% url 'users:login' %}">登录</a></div>            {% endblock %}        </div>

{% url 'users:login' %} 模板标签的作用是解析视图函数 users:login对应的URL模式。

这个模板标签接收的第一个参数为被解析视图函数的端点值,这个端点值由两个部分组成,中间用一个冒号相隔。冒号的第一部分为在应用的 urls.py 中确定的 app_name 的值。

冒号的第二部分为 path 函数中传入的参数 name 的值。如下图所示:

此模板标签最后对应的 url 为:users/login。

当然模板标签中,也是可以添加参数的,例如:{% url 'orders:detail' order.id %}。对应的 urls.py 中 path的定义一般为:path('order/<int:pk>/', views.detail, name='detail'),最后对应的 url 为:orders/order/2。

导航栏链接的显示控制

因为登录页面和注册页面也都继承了公共模板,所以目前无论是注册页面,还是点餐页面,这四个链接,都会直接显示出来。实际情况下,未登录时,将只显示登录和注册链接。登录之后,将只显示登陆账号,点餐和退出链接。

这里就需要使用到 session 和 cookie,跨页面传递数据。具体内容下一节“11-Session,Cookie”中详细介绍。

在点餐列表页面只显示登陆账号,点餐和退出链接,那么就需要,在模型中传递登录名模板中,而且在模板中,修改 navbar 的内容。打开 templates/orders/index.html 的 nevbar 块:

{% block nevbar %}    {% if username %}    <div class="flow-left"><a href="{% url 'orders:index' %}">点餐</a></div>    <div class="flow-right"><a href="{% url 'users:logout' %}">退出</a></div>    <div class="flow-right"> 欢迎:{{ username }} 登陆系统! </div>    {% else %}    <div class="flow-right"><a href="{% url 'users:regist' %}">注册</a></div>    <div class="flow-right"><a href="{% url 'users:login' %}">登录</a></div>    {% endif %}{% endblock%}

在 orders/models.py 中修改,返回 username 信息:

def order(request):    ticket = request.COOKIES.get('ticket')    .......    context = {'orders':orders,'username':request.COOKIES.get('username')}    return render(request, 'orders/index.html', context)
分页显示数据

例如 orders 首页目前是在一个页面中显示所有今天的订单,这样数据太多,如果能分页显示,并进行翻页就好了。下面就讲解一下,如何在页面中分页显示数据。

Django提供了一个新的类来帮助管理分页数据,这个类存放在 django/core/paginator.py。它可以接收列表、元组或其它可迭代的对象。

paginator.py的核心代码,如下:

class Paginator(object):     def __init__(self, object_list, per_page, orphans=0,                 allow_empty_first_page=True):        self.object_list = object_list        self.per_page = int(per_page)        self.orphans = int(orphans)        self.allow_empty_first_page = allow_empty_first_page ……

修改视图

在 orders/views.py 中添加相应代码:

from django.shortcuts import renderfrom datetime import datetimefrom django.http import HttpResponseRedirectfrom django.core.paginator import Paginator, EmptyPage, PageNotAnIntegerfrom .models import Orderfrom users.models import Userdef order(request):		#登陆验证    ticket = request.COOKIES.get('ticket')    if not ticket:        return HttpResponseRedirect('/users/login/')     user = User.objects.filter(ticket=ticket)    if not user:        return HttpResponseRedirect('/users/login/')	  获取当天的点餐数据    date_today = datetime.now().strftime('%Y-%m-%d')    order_list = Order.objects.filter(createdate__gte = date_today).order_by('dinnertime','-createdate')    #创建分页 Paginator 实例,每页显示5条数据    paginator = Paginator(order_list, 5) # Show 5 contacts per page    page = request.GET.get('page')    try:        orders = paginator.page(page)    except PageNotAnInteger:        # If page is not an integer, deliver first page.        orders = paginator.page(1)    except EmptyPage:        # If page is out of range (e.g. 9999), deliver last page of results.        orders = paginator.page(paginator.num_pages)    #向模板返回数据,包括用户名    context = {'orders':orders,'username':request.COOKIES.get('username')}    return render(request, 'orders/index.html', context)

修改 templates/orders/index.html:

{% extends 'base.html' %}{% block title %}    订单页面{% endblock%}{% block nevbar %}    {% if username %}    <div class="flow-left"><a href="{% url 'orders:index' %}">点餐</a></div>    <div class="flow-right"><a href="{% url 'users:logout' %}">退出</a></div>    <div class="flow-right"> 欢迎:{{ username }} 登陆系统! </div>    {% else %}    <div class="flow-right"><a href="{% url 'users:regist' %}">注册</a></div>    <div class="flow-right"><a href="{% url 'users:login' %}">登录</a></div>    {% endif %}{% endblock%}{% block section %}<div >    <h3>今日 {% now "Y-m-d" %} 订餐订单:</h3>    <table style="display: inline-block; ">        <tr>        <th>编号</th>        <th>姓名</th>        <th>下单时间</th>        <th>菜品</th>        <th>餐馆</th>        <th>数量</th>        <th>辣味</th>        <th>吃饭时间</th>        </tr>        {% for order in orders %}            <tr>                <td>{{ order.id }}</td>                <td>{{ order.username }}</td>                <td>{{ order.createdate }}</td>                <td>{{ order.dish }}</td>                <td>{{ order.dish.restaurant }}</td>                <td>{{ order.quantity }}</td>                    <td>{{ order.get_spicy_display }}</td>                    <td>{{ order.get_dinnertime_display }}</td> <!--显示中餐/午餐的value-->                </tr>        {% endfor %}                    </table>    <div class="pagination">        <span class="step-links">            {% if orders.has_previous %}                <a href="?page={{ orders.previous_page_number }}" aria-label="previous">                    <span aria-hidden="true">上一页</span>                </a>            {% endif %}                 <span class="current">                第 {{ orders.number }} 页(共 {{ orders.paginator.num_pages }} 页)            </span>                 {% if orders.has_next %}                <a href="?page={{ orders.next_page_number }}" aria-label="next">                    <span aria-hidden="true">下一页</span>                </a>            {% endif %}        </span>    </div></div>{% endblock%}

显示结果如下图所示:

可能的异常错误:

django.core.exceptions.ImproperlyConfigured: WSGI application 'iorder.wsgi.application' could not be loaded; Error importing module.

如果是使用了中间件 middleware,需要安装WSGI模块

pip install django-cors-headers

建议按照 项目实战Django Web开发-16-目录结构 的顺序进行学习 iorder 项目的开发过程。

源代码在 github 中:

标签: #页面导航分页算法有哪些