Python之路Day19
志不坚者智不达。
主要内容: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">«</span>
</a>
</li>
{% else %}
<li class="disabled">
<a href="" aria-label="Previous">
<span aria-hidden="true">«</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">»</span>
</a>
</li>
{% else %}
<li class="disabled">
<a href="" aria-label="Previous">
<span aria-hidden="true">»</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">«</span></a></li>
{% else %}
<li class="disabled"><a href="" aria-label="Previous"><span aria-hidden="true">«</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">»</span></a></li>
{% else %}
<li class="disabled"><a href="" aria-label="Previous"><span aria-hidden="true">»</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">«</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">«</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">»</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">»</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的更多相关文章
- Python之路,Day19 - CMDB、CMDB、CMDB
Python之路,Day19 - CMDB.CMDB.CMDB 本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT ...
- Python学习路程day19
Python之路,Day19 - Django 进阶 本节内容 自定义template tags 中间件 CRSF 权限管理 分页 Django分页 https://docs.djangoproj ...
- Python之路【第一篇】python基础
一.python开发 1.开发: 1)高级语言:python .Java .PHP. C# Go ruby c++ ===>字节码 2)低级语言:c .汇编 2.语言之间的对比: 1)py ...
- Python之路
Python学习之路 第一天 Python之路,Day1 - Python基础1介绍.基本语法.流程控制 第一天作业第二天 Python之路,Day2 - Pytho ...
- python之路 目录
目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...
- Python之路【第十九篇】:爬虫
Python之路[第十九篇]:爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用 ...
- Python之路【第十八篇】:Web框架们
Python之路[第十八篇]:Web框架们 Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...
- Python之路【第十七篇】:Django【进阶篇 】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十六篇】:Django【基础篇】
Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...
随机推荐
- 关于 overridePendingTransition()使用
实现两个 Activity 切换时的动画.在Activity中使用有两个参数:进入动画和出去的动画. 注意1.必须在 StartActivity() 或 finish() 之后立即调用.2.而且在 ...
- 学习pthreads,给线程传递多个參数
上篇博文中.boss线程给其它线程传递的仅仅有一个參数,那么假如是多个參数呢?怎么传递呢?也许你会有这种疑问,带着这个疑问,我们进入本文的世界,这里传递多个參数,採用结构体,为什么呢?由于结构体里能够 ...
- sql的强大功能(看一条sql解决的复杂业务)
一条sql语句解决的复杂业务,请往下看: 业务介绍:一个单位有多个立项(立项信息表里有单位id),每个立项可能被预警多次(预警信息表里的uuid字段的值里包含有立项id或单位id),每 ...
- g711u与g729比較编码格式
•711a-编解码格式为G.711 alaw •g711u-编解码格式为G.711 ulaw (the default) •g729-编解码格式为G.729 •g729a-编解码格式为G.729a 上 ...
- golang(5):编写WebSocket服务,client和html5调用
本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/46882777 转载请必须注明出处! 1.关于websocket HTML5定义了 ...
- linux之线程
http://blog.csdn.net/lanyan822/article/details/7586845 POSIX线程数据类型: pthread_t 线程标识符: pthread_mutex_t ...
- STL-multimap
转自:http://www.cnblogs.com/xiaoka/archive/2011/08/09/2132342.html multimap提供了可以一种可以有重复键值的STL map类型.其插 ...
- UVa1225 Digit Counting
#include <stdio.h>#include <string.h> int main(){ int T, N, i, j; int a[10]; sc ...
- 手机浏览器下IScroll中click事件
产品的h5页面几乎都使用了iscroll插件,如果a标签在iscroll里,在部分手机浏览器中会出现无法点击的情况,不管是绑定click事件还是使用a标签的href属性.href属性偶尔还会能点击,c ...
- Python学习笔记 (3) :列表、元组的操作
列表,即写在方括号之间.用逗号分隔开的数值列表.列表内的项目不必全是相同的类型. >>> a = ['spam', 'eggs', 100, 1234] >>> a ...