志不坚者智不达。

主要内容:Django分页、自定义simpletag、权限管理

Django分页

Django自带了一个分页功能,使用起来很方便。官方文档

先来看一下效果图:

后台代码:

def customers(request):
    customers_set = models.Customer.objects.all()
    # 生成分页实例,第一个参数为query_set对象,第二个参数为每页显示多少条数据
    paginator = Paginator(customers_set, 1)
    # 从请求中获取页码
    page = request.GET.get("page")
    try:
        customers_iter = paginator.page(page)
    # 如果获取的page不是数字,就默认返回第一页
    except PageNotAnInteger:
        customers_iter = paginator.page(1)
    # 如果获取的page不存在,就默认返回最后一页
    except EmptyPage:
        customers_iter = paginator.page(paginator.num_pages)

    return render(request, "crm/customers.html", {"customers": customers_iter})

前端代码:

<nav>
    <ul class="pagination">
    {% if customers.has_previous %}
        <li class="">
            <a href="?page={{ customers.previous_page_number }}" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>
    {% else %}
        <li class="disabled">
            <a href="" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>
    {% endif %}
    {% for page in customers.paginator.page_range %}
        {% if page == customers.number %}
            <li class="active"><a href="?page={{ page }}">{{ page }}</a></li>
        {% else %}
            <li class=""><a href="?page={{ page }}">{{ page }}</a></li>
        {% endif %}
    {% endfor %}
    {% if customers.has_next %}
        <li class="">
            <a href="?page={{ customers.next_page_number }}" aria-label="Previous">
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>
    {% else %}
        <li class="disabled">
            <a href="" aria-label="Previous">
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>
    {% endif %}
    </ul>
</nav>

这个方法默认会把所有的页数显示出来,这就会有一个问题就是如果页数特别多显示出来就不好看了。

所有还要优化一下,如下图:

前端代码:

<nav>
    <ul class="pagination">
    {% if customers.has_previous %}
    <li class=""><a href="?page={{ customers.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
    {% else %}
    <li class="disabled"><a href="" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
    {% endif %}
    {% for page in customers.paginator.page_range %}
        {% get_show_pages customers.number page %}
    {% endfor %}
    {% if customers.has_next %}
      <li class=""><a href="?page={{ customers.next_page_number }}" aria-label="Previous"><span aria-hidden="true">&raquo;</span></a></li>
    {% else %}
    <li class="disabled"><a href="" aria-label="Previous"><span aria-hidden="true">&raquo;</span></a></li>
    {% endif %}
    </ul>
</nav>

这里就用到了一个自定义的simpletag:

get_show_pages.py

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# __author__ = "Q1mi"
# Email: master@liwenzhou.com

from django import template
from django.utils.html import format_html

register = template.Library()

@register.filter
def value_upper(val):
    return val.upper()

# 获得需要展示的页码数
@register.simple_tag
def get_show_pages(current_page, loop_num):
    offset = abs(current_page - loop_num)
    # 只显示当前页前后三页的页码数
    if offset < 3:
        if current_page == loop_num:
            page_str = '<li class="active"><a href="?page={}">{}</a></li>'.format(loop_num, loop_num)
        else:
            page_str = '<li class=""><a href="?page={}">{}</a></li>'.format(loop_num, loop_num)
        return format_html(page_str)
    else:
        return ""

当然还可以用一个simpletag直接完成整个分页的前端展示功能。

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# __author__ = "Q1mi"
# Email: master@liwenzhou.com

from django import template
from django.utils.html import format_html

register = template.Library()

# 直接把整个分页功能写成一个单独的simple_tag,方便复用
@register.simple_tag
def show_pages(obj, show_num):
    """
    自定义的一个分页功能
    :param obj: paginator对象
    :param show_num: 当前页前后要显示的页码数
    :return:
    """
    global previous_page_str
    global next_page_str
    show_pages_str = ''
    if obj.has_previous():  # 如果有上一页就显示左<<标志可点
        previous_page_str = '''
            <li class="">
                <a href="?page={}" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
            </li>'''.format(obj.previous_page_number())
    else:  # 没有上一页就给li标签添加一个disabled class,即显示<<不可点击
        previous_page_str = '''
            <li class="disabled">
                <a href="" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
            </li>'''
    for page in obj.paginator.page_range:  # 便利页码
        if abs(obj.number - page) < show_num:  # 如果在要显示的范围内
            if obj.number == page:  # 如果是当前页,就给当前的li标签添加一个active的class
                show_pages_str += '''
                    <li class="active">
                        <a href="?page={}">{}</a>
                    </li>
                    '''.format(page, page)
            else:  # 否则li标签就不加active
                show_pages_str += '''
                    <li class="">
                        <a href="?page={}">{}</a>
                    </li>'''.format(page, page)
    if obj.has_next():  # 如果有下一页
        next_page_str = '''
            <li class="">
                <a href="?page={}" aria-label="Previous">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>'''.format(obj.next_page_number())
    else:  # 没有下一页,就给li标签加一个disabled的class
        next_page_str = '''
            <li class="disabled">
                <a href="" aria-label="Previous">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>'''
    html_str = "{}{}{}".format(previous_page_str, show_pages_str, next_page_str)  # 得到整个html字符串
    return format_html(html_str)  # 渲染返回给前端

simpletag实现一个独立的分页

自定义template tags

自定义的template tags 用于扩展Django 模板的功能。官方文档

首先要使用自定义的template tags就需要在app下,建一个与models.py和views.py同级的templatetags模块,在这个模块下写自定义的simple tag py文件。

其次在使用该自定义simple tag的模板中,使用{% load xxx %}导入自定义的simple tag:xxx,引用的时候直接写xxx.py内的定义的方法名即可。

template filters

一个最简单的例子,返回变量的大写:

from django import template

register = template.Library()

@register.filter
def value_upper(val):
    return val.upper()

在前端使用 {{ your_value | value_upper }}就可以把your_value变成大写了。

当然还有stringfilter等,可以查看官方文档。

simple tags

simple tag 能实现的功能就比较复杂了。

from django import template
from django.utils.html import format_html

register = template.Library()

# 获得需要展示的页码数
@register.simple_tag
def get_show_pages(current_page, loop_num):
    offset = abs(current_page - loop_num)
    # 只显示当前页前后三页的页码数
    if offset < 3:
        if current_page == loop_num:
            page_str = '<li class="active"><a href="?page={}">{}</a></li>'.format(loop_num, loop_num)
        else:
            page_str = '<li class=""><a href="?page={}">{}</a></li>'.format(loop_num, loop_num)
        return format_html(page_str)
    else:
        return ""

一个simple tag例子

Django 1.9中新增了一个很NB的功能就是在前端赋值变量,即使用as语法来给一个变量赋值。

这里补充一个url的方法,用于在前端生成url。

我们可以在urls.py里面给url增加一个name="xxx"(相当于起个别名,在别处可以调用这条url的匹配关系),然后在前端调用这个方法。

如果url有正则命名的分组,那么在前端在调用url时,必须给指定参数(正则的组)传值。

urls.py:

urlpatterns = [
    url(r'^(?P<word1>\w+)/(?P<word2>\w+)/from/Q1mi/$', views.url_name_test, name="url_name_test"),
]

前端:

<div style="margin: auto">
    <p>{% url "url_name_test" word1="hello" word2="world" %}</p>
    {% url "url_name_test" word1="hello" word2="world" as url_value %}
    <p>{{ url_value | value_upper }} </p>
</div>

网页:

/hello/world/from/Q1mi/
/HELLO/WORLD/FROM/Q1MI/

附老外的解答:

权限管理

django自带有基本的权限管理 ,但粒度和限制权限的维度都只是针对具体的表,如果我们想根据业务功能来限制权限,那就得自己写了,不过也不用完全自己的写,我们可以在django 自带的权限基础上轻松的实现扩展。

想对一个功能实现权限控制,要做到只能过在views类或方法上加一个装饰器就行。

Python之路Day19的更多相关文章

  1. Python之路,Day19 - CMDB、CMDB、CMDB

    Python之路,Day19 - CMDB.CMDB.CMDB   本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT ...

  2. Python学习路程day19

    Python之路,Day19 - Django 进阶   本节内容 自定义template tags 中间件 CRSF 权限管理 分页 Django分页 https://docs.djangoproj ...

  3. Python之路【第一篇】python基础

    一.python开发 1.开发: 1)高级语言:python .Java .PHP. C#  Go ruby  c++  ===>字节码 2)低级语言:c .汇编 2.语言之间的对比: 1)py ...

  4. Python之路

    Python学习之路 第一天   Python之路,Day1 - Python基础1介绍.基本语法.流程控制              第一天作业第二天   Python之路,Day2 - Pytho ...

  5. python之路 目录

    目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...

  6. Python之路【第十九篇】:爬虫

    Python之路[第十九篇]:爬虫   网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用 ...

  7. Python之路【第十八篇】:Web框架们

    Python之路[第十八篇]:Web框架们   Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...

  8. Python之路【第十七篇】:Django【进阶篇 】

    Python之路[第十七篇]:Django[进阶篇 ]   Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...

  9. Python之路【第十六篇】:Django【基础篇】

    Python之路[第十六篇]:Django[基础篇]   Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...

随机推荐

  1. WS_CLIPCHILDREN与WS_CLIPSIBLINGS 收藏

    英文单词解释clip:夹子.子弹夹.回形针:夹住,修剪sibling:同胞兄弟或姐妹overlapped:重叠 这两个Window Stype的特性与异同素来不太清楚,今日作一笔记:MSDN的解释为: ...

  2. BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊(动态树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2002 [题目大意] 给出一片森林,操作允许更改一个节点的父亲,查询一个节点的深度. [ ...

  3. C程序的存储空间布局

    历史沿袭至今,C程序一直由下列几部分组成: 1. 正文段.这是由CPU执行的机器指令部分.通常,正文段是可共享的,所以即使是频繁执行的程序(编辑器,编译器,命令解释器)在存储器中也只需一个副本,另外正 ...

  4. ZOJ 3430 Detect the Virus(AC自动机)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3430 题意:给你n个编码后的模式串,和m个编码后的主串,求原来主 ...

  5. Structs

    1.服务端的运行程序 2.Servlet的三个方法 init service:抽象方法 destroy 3.步骤 (1).在web.xml中 <servlet> <servlet-n ...

  6. HTTP协议头部与Keep-Alive模式详解

    HTTP协议头部与Keep-Alive模式详解 .什么是Keep-Alive模式? 我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器 ...

  7. poj 3764 The xor-longest Path Trie

    题目链接 求树上的一条最长异或路径. 定义f(u, v)为u到v的路径, 那么显然f(1, u)^f(1, v) = f(u, v), 想不到这个就没有办法做. 然后就可以用字典树查询+插入了. 用指 ...

  8. A Byte of Python 笔记(11)异常:try..except、try..finally

    第13章 异常 当你的程序中出现某些 异常的 状况的时候,异常就发生了. 错误 假如我们把 print 误拼为 Print,注意大写,这样 Python 会 引发 一个语法错误. 有一个SyntaxE ...

  9. cocos2d-x spine 加载粒子特效

    spine骨骼加载粒子效果 将粒子效果加到骨骼上,update位置和角度.h#ifndef __HOMESCENE_H__#define __HOMESCENE_H__#include "c ...

  10. ubuntu vim终端编辑命令

    一. VIM高亮 进入vim后,在普通模式下输入如下命令,开启php代码高亮显示   :syntax enable   :source $VIMRUNTIME/syntax/php.vim   二. ...