bootstrap之分页、cache,模态框登录注册等
一、bootstrap与分页之模板
继承bootstrap/base.html里面已经导入bootstrap需要的东西, 剩下填坑,Bootstrap自带模板
1.导航条
{% block navbar %}
从bootstrap复制,根据自己要求修改,一定要仔细看清复制结构
{% block navbar %}
2.主体内容
{% block content %}
<div>
用于固定宽度并支持响应式布局的容器,加一个DIV,将内容放到一个容器中,方便调整百分百,加入巨幕
</div>
{% endblock %}
二、bootstrap与分页之视图
1.手动实现分页(python代码)
@blue.route('/paginator/')
@blue.route('/paginator/<int:page>/')
def paginate(page=1,num=5):
# goods = Goods.query.offset(0).limit(5)
# goods = Goods.query.offset(5).limit(5)
# goods = Goods.query.offset(10).limit(5)
goods = Goods.query.offset((page-1)*5).limit(num)
return render_template('index.html',goods=goods)
2.flask自带分页(paginate)
查询数据,使用paginate方法获取对象,进行传值
@blue.route('/paginate/<int:page>/<int:num>')
def paginate(page,num):
# page 页码 num 显示数
paginate = Goods.query.paginate(page,num)
return render_template('paginate.html',paginate=paginate)
模板中:paginate的属性
当前页码:paginate.page
上一页页码:paginate.prev_num
下一页页码:paginate.next_num
有无上一页:paginate.has_prev
有无下一页:paginate.has_next
查询总页数:paginate.pages
记录总数:paginate.total
每页记录数量:paginate.per_page
分页导航列表:paginate.iter_pages( ) # 方法
当前页的记录内容:paginate.items
# paginate,对象,包含当前页的数据,paginate.items可被for循环遍历,每个遍历值为一个模型对象
3.分页导航的实现
(1)视图函数的编写,获取页码,查询数据,返回渲染
重点:获取反向解析的页码数,使用paginate方法获取页码数据
pagination包含了所有需要的参数,包括数据,即一个paginate对象搞定所有。
# 分页导航反向解析调用的函数
# 使用flask自带(paginate) 分页宏定义,自带的宏点击页数数使用反向解析找数据,会GET请求传回一个page页码
# 反向解析的地址是:127.0.0.1/paginate(这儿是什么并不重要,反向解析找函数,只要与下面地址对应就行)/?page=?
@blue.route('/paginate/')
def paginate():
# 先获取想要取得数据的页码,不传值时,给get一个默认值,默认是首页
page = int(request.args.get('page',1))
paginate = Goods.query.paginate(page,5)
return render_template('paginte.html',paginate=paginate)
(2)宏定义的编写,需要传两个参数,pagination为获取到的对象,endpoint为反向解析地址 蓝图名.函数名,page为请求页码
{#flask自带宏定义#}
{% macro render_pagination(pagination, endpoint) %}
<div class=pagination>
{%- for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
<a href="{{ url_for(endpoint, page=page) }}">{{ page }}</a>
{% else %}
<strong>{{ page }}</strong>
{% endif %}
{% else %}
<span class=ellipsis>…</span>
{% endif %}
{%- endfor %}
</div>
{% endmacro %}
{# 修改,引用bootstrap,有样式的宏定义 #}
{% macro pagination_widget(pagination, endpoint) %}
<ul class="pagination">
<li{% if not pagination.has_prev %} class="disabled"{% endif %}>
<a href="{% if pagination.has_prev %}{{ url_for(endpoint,page = pagination.page - 1, **kwargs) }}
{% else %}#{% endif %}">«
</a>
</li>
{% for p in pagination.iter_pages() %}
{% if p %}
{% if p == pagination.page %}
<li class="active">
<a href="{{ url_for(endpoint, page = p, **kwargs) }}">{{ p }}</a>
</li>
{% else %}
<li>
<a href="{{ url_for(endpoint, page = p, **kwargs) }}">{{ p }}</a>
</li>
{% endif %}
{% else %}
<li class="disabled">
<a href="#">…</a>
</li>
{% endif %}
{% endfor %}
<li{% if not pagination.has_next %} class="disabled"{% endif %}>
<a href="{% if pagination.has_next %}{{ url_for(endpoint,page = pagination.page + 1, **kwargs) }}{% else %}#{% endif %}">»</a>
</li>
</ul>
{% endmacro %}
(3)引用宏,
# 宏定义,分页导航#}
{# {% from 'appmacro.html' import render_pagination %}#}
{% from 'appmacro.html' import pagination_widget %}
{% if paginate %}
<div class="pagecontroller">
{# {{ render_pagination(paginate,'blue.paginate') }}#}
{{ pagination_widget(paginate, 'blue.paginate') }}
</div>
{% endif %}
小知识:ID一般使用在模板头部身体,底部,外部或大模块使用,其他用class;
模板一般获取到值时,循环前先判断是否为真 。
三、缓存cache
目的:在应用中添加缓存,缓存的目的是提高服务器的性能,提高网络访问的速度。缓存减少原生
数据库的操作,或说是减少磁盘的IO。
DebugToolbarExtension,只需在ext.py中实例化,初始化就行
1.cache缓存时,下载使用pip install flask-ceching
老版本cache会引起一系列问题,因此使用它的分支ceching(使用都是一致的,就是导包时不同
)
2.在扩展文件中实例化cache = Cache('CACHE_TYPE':'simple'),并初始化
3.视图中函数引用,哪里用放哪里
例:@cache.cached(timeout=60)
注意:这个要放在路径底下,否则无用,不会进入缓存
代码实例
@blue.before_request
def before_request():
key = request.remote_addr
# 从缓存中拿出连接的IP
value= cache.get(key)
print(value)
if value: # 拿到说明不是第一次连接了
abort(404)
else: # 说明第一次连接,给它设置一个key,下次再连接就可以判断
cache.set(key,'爬手'+key,timeout=3) # 此key存在时间在请求钩子函数和视图函数之间共享数据一般使用上下文全局变量g。
6.g (global全部的 )
钩子中定义后可在全局使用
# 钩子,AOP反爬策略
@blue.before_request
def before_request():
# # AOP反爬代码
# key = request.remote_addr
# # 从缓存中拿出连接的IP
# value= cache.get(key)
# print(value)
# if value: # 拿到说明不是第一次连接了
# abort(404)
# else: # 说明第一次连接,给它设置一个key,下次再连接就可以判断
# cache.set(key,'爬手'+key,timeout=3) # 此key存在时间
userid = session.get('userid')
if userid:
g.user = User.query.get(userid)
else:
g.user = None
(2)首页
# 首页
@blue.route('/index/')
# @cache.cached(timeout=10)
def index():
page = int(request.args.get('page', 1))
paginate = Goods.query.paginate(page, 5)
userid = session.get('userid')
# if userid:
# user = User.query.get(userid)
# else:
# user = None
return render_template('paginte.html',paginate=paginate,user=g.user)
(3)注册
# 注册
@blue.route('/register/',methods=['POST'])
def register():
user = User()
user.username = request.form.get('username')
user.password = request.form.get('password')
db.session.add(user)
db.session.commit()
# 此处设置session,注册后自动登录,跳到首页,已经有用户信息、
# 服务端 session [key:value] 'userid':1
# 客户端 cookie [key:value] 'session':'sessionkey'
session['userid'] = user.id
return redirect(url_for('five.index'))
(5)登录
# 登录
@blue.route('/login/',methods=['POST'])
def login():
username = request.form.get('username')
password = request.form.get('password')
# 进入数据库匹配,时刻记着过滤逻辑删除值
users = User.query.filter(User.isdelete == False).filter(User.username == username and User.password == password)
# 过滤出来后,不能确实是否是一个数据
if users.count():
user = users.first()
session['userid'] = user.id
else:
return '你的用户名或密码不正确'
return redirect(url_for('five.index'))
配置 说明 CACHE_DEFAULT_TIMEOUT 默认过期/超时时间,单位为秒 CACHE_DIR 存储缓存的目录 CACHE_THRESHOLD 缓存的最大条目数 CACHE_ARGS 在缓存类实例化过程中解包和传递的可选列表 CACHE_OPTIONS 可选字典在缓存类实例化期间传递