#!/usr/bin/python
# -*- coding: utf-8 -*-
__author__ = 'mrs.wc'
__filename__ = 'page_tools'
__datetime__ = '2018/3/1 21:39'
from urllib import urlencode, quote, unquote
class Pagination(object):
"""
自定义分页
"""
def __init__(self, current_page, total_count, base_url, params, per_page_count=10, max_pager_count=5):
try:
current_page = int(current_page)
except Exception as e:
current_page = 1
if current_page <= 0:
current_page = 1
self.current_page = current_page
# 数据总条数
self.total_count = total_count
# 每页显示10条数据
self.per_page_count = per_page_count
# 页面上应该显示的最大页码
max_page_num, div = divmod(total_count, per_page_count)
if div:
max_page_num += 1
self.max_page_num = max_page_num
# 页面上默认显示11个页码(当前页在中间)
self.max_pager_count = max_pager_count
self.half_max_pager_count = int((max_pager_count - 1) / 2)
# URL前缀
self.base_url = base_url
# request.GET
import copy
params = copy.deepcopy(params)
# params._mutable = True
get_dict = params.to_dict()
# 包含当前列表页面所有的搜/索条件
# {source:[2,], status:[2], gender:[2],consultant:[1],page:[1]}
# self.params[page] = 8
# self.params.urlencode()
# source=2&status=2&gender=2&consultant=1&page=8
# href="/hosts/?source=2&status=2&gender=2&consultant=1&page=8"
# href="%s?%s" %(self.base_url,self.params.urlencode())
self.params = get_dict
@property
def start(self):
return (self.current_page - 1) * self.per_page_count
@property
def end(self):
return self.current_page * self.per_page_count
def page_html(self):
# 如果总页数 <= 11
if self.max_page_num <= self.max_pager_count:
pager_start = 1
pager_end = self.max_page_num
# 如果总页数 > 11
else:
# 如果当前页 <= 5
if self.current_page <= self.half_max_pager_count:
pager_start = 1
pager_end = self.max_pager_count
else:
# 当前页 + 5 > 总页码
if (self.current_page + self.half_max_pager_count) > self.max_page_num:
pager_end = self.max_page_num
pager_start = self.max_page_num - self.max_pager_count + 1 # 倒这数11个
else:
pager_start = self.current_page - self.half_max_pager_count
pager_end = self.current_page + self.half_max_pager_count
page_html_list = []
# {source:[2,], status:[2], gender:[2],consultant:[1],page:[1]}
# 首页
self.params['page'] = 1
first_page = '首页 ' % (self.base_url, urlencode(self.params),)
page_html_list.append(first_page)
# 上一页
self.params["page"] = self.current_page - 1
if self.params["page"] < 1:
pervious_page = '上一页 ' % (
self.base_url, urlencode(self.params))
else:
pervious_page = '上一页 ' % (
self.base_url, urlencode(self.params))
page_html_list.append(pervious_page)
# 中间页码
for i in range(pager_start, pager_end + 1):
self.params['page'] = i
if i == self.current_page:
temp = '%s ' % (self.base_url, urlencode(self.params), i,)
else:
temp = '%s ' % (self.base_url, urlencode(self.params), i,)
page_html_list.append(temp)
# 下一页
self.params["page"] = self.current_page + 1
if self.params["page"] > self.max_page_num:
self.params["page"] = self.current_page
next_page = '下一页 ' % (
self.base_url, urlencode(self.params))
else:
next_page = '下一页 ' % (
self.base_url, urlencode(self.params))
page_html_list.append(next_page)
# 尾页
self.params['page'] = self.max_page_num
last_page = '尾页 ' % (self.base_url, urlencode(self.params),)
page_html_list.append(last_page)
return ''.join(page_html_list)
#!usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask,render_template,request,redirect
from pager import Pagination
from urllib.parse import urlencode
app = Flask(__name__)
# =========================django的用法=======================================
# pager_obj = Pagination(request.GET.get('page', 1), len(HOST_LIST), request.path_info, request.GET)
# host_list = HOST_LIST[pager_obj.start:pager_obj.end]
# html = pager_obj.page_html()
# return render(request, 'hosts.html', {'host_list': host_list, "page_html": html})
@app.route('/pager')
def pager():
li = []
for i in range(1,100):
li.append(i)
# print(li)
# ===================================flask的用法===============================
pager_obj = Pagination(request.args.get("page",1),len(li),request.path,request.args,per_page_count=10)
# print(request.args)
index_list = li[pager_obj.start:pager_obj.end]
html = pager_obj.page_html()
return render_template("pager.html",index_list=index_list, html = html,condition=path)
if __name__ == '__main__':
app.run(debug=True)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width">
<title>Titletitle>
<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
<style>
.container {
margin-top: 20px;
}
style>
head>
<body>
<div class="container">
<a href="/add?{{ condition }}">
<button class="btn btn-primary">添加button>
a>
<div class="row " style="margin-top: 10px">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>表头1th>
<th>表头2th>
<th>表头3th>
<th>表头4th>
tr>
thead>
<tbody>
{% for foo in index_list %}
<tr>
<td>{{ foo[0] }}td>
<td>{{ foo[1] }}td>
<td>{{ foo[2] }}td>
<td>{{ foo[3] }}td>
tr>
{% endfor %}
tbody>
table>
<nav aria-label="Page navigation" class="pull-right">
<ul class="pagination">
{{ html|safe }}
ul>
nav>
div>
div>
body>
html>
#!/usr/bin/python
# -*- coding: utf-8 -*-
__author__ = 'mrs.wc'
__filename__ = 'demo'
__datetime__ = '2018/3/1 21:41'
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
from flask import Flask, render_template, request, redirect
from page_tools import Pagination
from urllib import urlencode
app = Flask(__name__)
# =========================django的用法=======================================
# pager_obj = Pagination(request.GET.get('page', 1), len(HOST_LIST), request.path_info, request.GET)
# host_list = HOST_LIST[pager_obj.start:pager_obj.end]
# html = pager_obj.page_html()
# return render(request, 'hosts.html', {'host_list': host_list, "page_html": html})
# =========================flask的用法========================================
@app.route('/pager')
def pager():
temp=('浙江大学','天津大学','北京大学','牛津大学')
li = []
for i in range(1, 1000000):
li.append(temp)
# print(li)
pager_obj = Pagination(request.args.get("page", 1), len(li), request.path, request.args, per_page_count=15)
print request.args
print request.path
index_list = li[pager_obj.start:pager_obj.end]
html = pager_obj.page_html() # request.path
return render_template("pagers.html", index_list=index_list, html=html, condition=None)
if __name__ == '__main__':
app.run(debug=True)
项目需要的的基础环境包配置:
安装方式:将需要安装的包保存在aa.txt中, cd到requirement.txt所在目录,运行:
pip批量安装package: pipinstall−rrequirement.txtpip批量卸载package: p i p i n s t a l l − r r e q u i r e m e n t . t x t p i p 批 量 卸 载 p a c k a g e : pip uninstall -r requirement.txt
alembic==0.9.8
aniso8601==2.0.0
astroid==1.6.0
backports-abc==0.5
backports.functools-lru-cache==1.4
backports.shutil-get-terminal-size==1.0.0
bleach==2.1.2
certifi==2017.11.5
click==6.7
colorama==0.3.9
configparser==3.5.0
cycler==0.10.0
decorator==4.1.2
Django==1.10.5
entrypoints==0.2.3
enum34==1.1.6
Flask==0.12.2
Flask-Migrate==2.1.1
Flask-RESTful==0.3.6
Flask-Script==2.0.6
Flask-SQLAlchemy==2.3.2
functools32==3.2.3.post2
html5lib==1.0.1
http==0.2
ipykernel==4.7.0
ipython==5.5.0
ipython-genutils==0.2.0
ipywidgets==7.1.0
isort==4.2.15
itsdangerous==0.24
Jinja2==2.10
jsonschema==2.6.0
jupyter-client==5.2.1
jupyter-core==4.4.0
lazy-object-proxy==1.3.1
Mako==1.0.7
MarkupSafe==1.0
matplotlib==2.1.1
mccabe==0.6.1
memory-profiler==0.52.0
mistune==0.8.3
MySQL-python==1.2.5
nbconvert==5.3.1
nbformat==4.4.0
notebook==5.2.2
numpy==1.14.0
pandocfilters==1.4.2
pathlib2==2.3.0
pickleshare==0.7.4
Pillow==5.0.0
prompt-toolkit==1.0.15
psutil==5.4.3
Pygments==2.2.0
pylint==1.8.1
pymssql==2.1.3
PyMySQL==0.8.0
pyparsing==2.2.0
pypiwin32==223
python-dateutil==2.6.1
python-editor==1.0.3
pytz==2017.3
pywin32==223
pyzmq==16.0.3
scandir==1.6
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.11.0
SQLAlchemy==1.2.4
testpath==0.3.1
tornado==4.5.2
traitlets==4.3.2
wcwidth==0.1.7
webencodings==0.5.1
Werkzeug==0.12.2
widgetsnbextension==3.1.0
win-unicode-console==0.5
WMI==1.4.9
wrapt==1.10.11
xlrd==1.1.0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@ __file_name__ = 'models.py'
@ __author__ = 'Empathy'
@ __time__ = '2017/9/24 21:28'
"""
from exits import db
from datetime import datetime
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
telphone = db.Column(db.String(11), nullable=False)
username = db.Column(db.String(50), nullable=False)
password = db.Column(db.String(10), nullable=False)
class Question(db.Model):
__tablename__ = 'question'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
# 1.datetime.now()服务器运行的时间
# 2.datetime.now,每次数据模型生成的时间
create_time = db.Column(db.DateTime, default=datetime.now)
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
# 关联查询,反转查询
author = db.relationship('User', backref=db.backref('questions'))
class Answer(db.Model):
__tablename__ = 'answer'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
content = db.Column(db.Text, nullable=False)
create_time = db.Column(db.DateTime, default=datetime.now)
# 1.关联外键,指定表名.主键字段
question_id = db.Column(db.Integer, db.ForeignKey('question.id'))
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
# 2.反转查询,指定模型类名,反转对象名称
question = db.relationship('Question', backref=db.backref('answers', order_by=id.desc()))
author = db.relationship('User', backref=db.backref('answers'))
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
# debug模式
DEBUG = True
# 24位随机cookia加密
SECRET_KEY =os.urandom(24)
# dialect+driver://username:password@host:port/database
# mysql数据库配置
DIALECT = 'mysql'
DRIVER = 'mysqldb'
USERNAME = 'xxx'
PASSWORD = 'xxxx'
HOST = '127.0.0.1'
PORT = '3306'
DATABASE = 'xxx'
DB_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)
SQLALCHEMY_DATABASE_URI = DB_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False
# DATA_BASE_INFO ={
# 'DIALECT': 'mysql',
# 'DRIVER': 'mysqldb',
# 'USERNAME': 'xxx',
# 'PASSWORD': 'xxx',
# 'HOST': '127.0.0.1',
# 'PORT': '3306',
# 'DATABASE': 'xxx',
# 'CHARSET': 'utf8'
# }
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@ __file_name__ = 'decorators.py'
@ __author__ = 'Empathy'
@ __time__ = '2017/9/27 0:45'
"""
from functools import wraps
from flask import session,render_template,redirect,url_for
# 定义一个登录现在的装饰器
def login_require(func):
@wraps(func)
def wrapper(*args,**kwargs):
if session.get('user_id'):
return func(*args, **kwargs)
else:
return redirect(url_for('login'))
return wrapper
# 高级函数-闭包,函数嵌套,返回返回对象本身
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@ __file_name__ = 'manage.py'
@ __author__ = 'Empathy'
@ __time__ = '2017/9/24 21:29'
"""
# import sys
# reload(sys)
# sys.setdefaultencoding('utf-8')
from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from zhiliao import app
from exits import db
from models import User,Question
# 使用manager绑定app
manager = Manager(app)
# 使用migrate绑定app和db
migrate = Migrate(app, db)
# 添加迁移数据库脚本命令道manager中
manager.add_command('db',MigrateCommand)
if __name__ == '__main__':
manager.run()
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
{% block title %}{% endblock %}-知了课堂问答平台
title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script sre="https://cdn.bootcss.com/jquery/3.2.1/jquery.js">script>
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous">script>
<link rel="stylesheet" href="{{ url_for('static',filename='css/base.css') }}">
{% block head %}{% endblock %}
head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a class="navbar-brand" href="">
<img class="logo" src="{{url_for('static',filename='images/log.png')}}" alt="">
a>
div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="/">
<a href="{{ url_for('index') }}">
首页 <span class="sr-only">(current)span>
a>
li>
<li>
<a href="{{ url_for('question') }}">发布问答a>
li>
ul>
<form class="navbar-form navbar-left" action="{{ url_for('search') }}" method="get">
<div class="form-group">
<input name="q" type="text" class="form-control" placeholder="请输入关键字">
div>
<button type="submit" class="btn btn-default">搜索button>
form>
<ul class="nav navbar-nav navbar-right">
{% if user %}
<li><a href="#"> {{ user.username }}a>li>
<li><a href="{{ url_for('logout') }}"> 注销a>li>
{% else %}
<li><a href="{{ url_for('login') }}">登录a>li>
<li><a href="{{ url_for('regist') }}">注册a>li>
{% endif %}
ul>
div>
div>
nav>
<div class="main">
{% block main %}{% endblock %}
div>
body>
html>
{% extends 'base.html' %}
{% block title %}首页{% endblock %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static',filename='css/index.css') }}">
{% endblock %}
{% block main %}
<ul>
{% for question in data_list %}
<li>
<div class="avatar-group">
<img src="{{ url_for('static',filename='images/question.png')}}" alt="" class="avatar">
div>
<div class="question-group">
<p class="question-title">
<a href="{{ url_for('detail',question_id=question.id)}}">{{ question.title }}a>
p>
<p class="question-content">
{{ question.content }}
p>
<div class="question-info">
<span class="question-author">{{ question.author.username }}span>
<span class="question-time">{{ question.create_time }}span>
div>
div>
li>
{% endfor %}
ul>
<nav aria-label="Page navigation" class="pull-right">
<ul class="pagination">
{{ html|safe }}
ul>
nav>
{% endblock %}
#!/usr/bin/python
# -*- coding: utf-8 -*-
__author__ = 'mrs.wc'
__filename__ = 'page_tools'
__datetime__ = '2018/3/1 21:39'
# 导入Flask基本模块类
from flask import Flask,render_template,request,redirect,url_for,session,g
import config
from models import User,Question,Answer
from exits import db
import datetime
from decorators import login_require
from sqlalchemy import or_
# 初始化一个Flask对象
# Flask()
# 需要传递一个参数 __name__
# 1.方便框架去寻找资源
# 2. 方便flask 插件如flask SqlAlchemy 出错寻找错误位置
app = Flask(__name__)
app.config.from_object(config)
# 初始化app数据库
db.init_app(app)
from utils import page_utils
# @app.route()是一个装饰器
# @开头,在函数上面,表示装饰器
# 这个装饰器的作用:一个url和试图的映射关系
# web应用首页
@app.route('/')
def index():
context ={
'questions': Question.query.order_by('-create_time').all()
}
all_data_list=context.get('questions',[])
data_list,html=page_utils.page_paginate(all_data_list,3)
return render_template('index.html',data_list=data_list,html=html,condition=None)
# 登录功能模块,用户信息入库,保持cookie到session
@app.route('/login/', methods=['GET', 'POST'])
def login():
if request.method=='GET':
return render_template('login.html')
else:
telphone = request.form.get('telphone')
password = request.form.get('password')
user = User.query.filter(User.telphone == telphone, User.password == password).first()
if user:
# 保存用户session信息
session['user_id']= user.id
# 如果需要31天保持登录
session.permanent = True
# 跳转到首页
return redirect(url_for('index'))
# return u'{}:你好,您已经登录成功!;当前时间:{}'.format(user.username,datetime.datetime.now())
else:
# return u'手机号或者登录密码失败!'
return render_template('loginerror.html')
# 注册功能模块,用户信息校验,入库
@app.route('/regist/', methods=['GET', 'POST'])
def regist():
if request.method=='GET':
return render_template('regist.html')
else:
telphone = request.form.get('telphone')
username = request.form.get('username')
password1 = request.form.get('password1')
password2 = request.form.get('password2')
#检验手机号,判断手机号是否注册
user = User.query.filter(User.telphone==telphone).first()
if user:
return u'手机号已注册,请更换手机号!'
# 密码校验,2次密码一样即可
if password1!=password2:
print password1,password2
return u'两次密码不同,请核对再提交!'
else:
user = User(telphone=telphone,username=username,password=password1)
db.session.add(user)
db.session.commit()
# 注册成功,跳转到登陆页面
return redirect(url_for('login'))
# 注销功能模块 , 清除 session 中的user_id
@app.route('/logout/')
def logout():
# session.pop('user_id')
# del session['user_id']
session.clear()
return redirect(url_for('login'))
# 发布问答功能,数据入库
@app.route('/question/',methods=['GET', 'POST'])
@login_require # 装饰器放在函数下面才生效
def question():
if request.method=="GET":
return render_template('question.html')
else:
title = request.form.get('title')
content = request.form.get('content')
question = Question(title=title, content=content)
# user_id = session.get('user_id')
# user = User.query.filter(User.id == user_id).first()
# question.author = user
question.author = g.user
db.session.add(question)
db.session.commit()
return redirect(url_for('index'))
# 问答详情页面,超链接跳转
@app.route('/detail//')
# @login_require
def detail(question_id):
# return redirect(url_for('detail'))
question_model= Question.query.filter(Question.id == question_id).first()
all_data_list=list(question_model.answers)
# question提供详细页面渲染使用
answers, html = page_utils.page_paginate(all_data_list, 3) # all_data_list.content
return render_template('detail.html',html=html, question=question_model,answers=answers)
# 发布评论,回答问题,限制只支持post提交
@app.route('/add_answer/', methods=['POST'])
@login_require
def add_answer():
content = request.form.get('answer_content')
question_id = request.form.get('question_id')
answer = Answer(content=content)
# user_id = session.get('user_id')
# user = User.query.filter(User.id == user_id).first()
# answer.author = user
answer.author = g.user
question = Question.query.filter(Question.id == question_id).first()
answer.question = question
db.session.add(answer)
db.session.commit()
# question提供详细页面渲染使用
return redirect(url_for('detail', question_id=question_id))
# 页面关键字搜索功能模块
@app.route('/search/')
def search():
q = request.args.get('q')
if q and not q is None:
condition = or_(Question.title.contains(q), Question.content.contains(q))
questions = Question.query.filter(condition)
all_data_list=list(questions)
data_list, html = page_utils.page_paginate(all_data_list, 3)
return render_template('index.html', html=html,data_list=data_list,condition=None)
else:
return render_template('index.html')
# # 查询-与操作 # title, content
# # questions = Question.query.filter(or_(Question.title.contains(q),\
# # Question.content.contains(q))).order_by('-create_time')
# # 查询-或操作 # title , content
# # condition=or_(Question.title.contains(key),Question.content.contains(key))
# condition = or_(Question.title.contains(q), Question.content.contains(q))
# questions = Question.query.filter(condition)
# # questions = Question.query.filter(condition)
# # questions = questions.order_by('-create_time').first().title
# # questions=questions 中第一个questions为models 中定义的关联表对象名称
# return render_template('index.html', questions=questions)
"""
flask 中的g对象,存放对象,可以调用
"""
# 代码优化,g对象存取常用对象
@app.before_request
def my_before_request():
user_id = session.get('user_id')
if user_id:
user = User.query.filter(User.id == user_id).first()
if user:
g.user=user
""" 钩子函数和视图函数,上下文处理函数 执行步骤:
# 1.首先 before_request -> views func() -> context_processor
# 2. 绑定user到g对象 ->views func() -> context_processor
"""
# 定义一个钩子函数,返回一个字典(变量可以供模板渲染),没有也要返回一个空字典对象
@app.context_processor
def my_context_processor():
if hasattr(g,'user'):
return {'user': g.user}
else:
return {}
# 定义一个钩子函数,返回一个字典(变量可以供模板渲染),没有也要返回一个空字典对象
# @app.context_processor
# def my_context_processor():
# user_id = session.get( 'user_id' )
# user = User.query.filter( User.id == user_id ).first( )
# if user:
# return {'user': user}
# else:
# return {}
if __name__ == '__main__':
app.run()