Flask是一个Python编写的Web 微框架,让我们可以使用Python语言快速实现一个网站或Web服务。
1.pip 安装所需依赖
Flask==0.12.2
Flask-Bootstrap==3.3.7.1
Flask-HTTPAuth==3.2.3
Flask-Login==0.4.0
Flask-Mail==0.9.1
Flask-Migrate==2.0.4
Flask-Moment==0.5.1
Flask-PageDown==0.2.2
Flask-Script==2.0.6
Flask-SQLAlchemy==2.2
Flask-SSLify==0.1.5
Flask-WTF==0.14.2
html5lib==0.999999999
importlib==1.0.4
itsdangerous==0.24
Jinja2==2.9.6
Markdown==2.6.8
MarkupSafe==1.0
MySQL-python==1.2.5
SQLAlchemy==1.1.11
Twisted==14.0.0
Werkzeug==0.12.2
WTForms==2.1
2.创建工程
目录结构为:
PoleStar --- app --- api --- __init__.py
| | users.py
| auth --- __init__.py
| | views.py
| main --- __init__.py
| | errors.py/views.py
| static
| |
| templates --- auth --- login.html
| __init.py main --- index.html/403.html/404.html/500.html
| config.py
run.py models.py
工程名为PoleStar,应用里面定义有api接口(api)、登录验证(auth)、主界面(main)、静态目录、模板目录
run.py
import os
from app import create_app
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
if __name__=="__main__":
app.run(host='0.0.0.0', port=5000, threaded=True)
app工厂函数__init__.py
from flask import Flask
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from config import config
bootstrap = Bootstrap()
db = SQLAlchemy()
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
bootstrap.init_app(app)
db.init_app(app)
login_manager.init_app(app)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth')
from .api import api as api_blueprint
app.register_blueprint(api_blueprint, url_prefix='/api/v1')
return app
config.py
# -*- coding: utf-8 -*-
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
LOGIN_MESSAGE = u'请从这个页面登录'
SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
POLESTAR_MAIL_SUBJECT_PREFIX = '[PoleStar]'
SSL_REDIRECT = False
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_RECORD_QUERIES = True
POLESTAR_POSTS_PER_PAGE = 6
POLESTAR_FOLLOWERS_PER_PAGE = 50
POLESTAR_COMMENTS_PER_PAGE = 30
POLESTAR_SLOW_DB_QUERY_TIME = 0.5
@staticmethod
def init_app(app):
pass
class DevelopmentConfig(Config):
DEBUG = False
SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \
"mysql://user:[email protected]/database"
# 'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')
config = {
'development': DevelopmentConfig,
# 'testing': TestingConfig,
# 'production': ProductionConfig,
'default': DevelopmentConfig
}
models.py
#coding:utf-8
from datetime import datetime
import hashlib
from werkzeug.security import generate_password_hash, check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from flask import current_app, url_for
from flask_login import UserMixin
from . import db, login_manager
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), unique=True, index=True)
username = db.Column(db.String(64), index=True)
nickname = db.Column(db.String(64))
# role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
password_hash = db.Column(db.String(128))
confirmed = db.Column(db.Boolean, default=False)
member_since = db.Column(db.DateTime(), default=datetime.utcnow)
last_seen = db.Column(db.DateTime(), default=datetime.utcnow)
original = db.Column(db.Integer, default=0)
fans = db.Column(db.Integer, default=0 )
like = db.Column(db.Integer, default=0)
comment = db.Column(db.Integer, default=0)
level = db.Column(db.Integer, default=0)
visitor_volume = db.Column(db.Integer, default=0)
ranking = db.Column(db.Integer, default=0)
integral = db.Column(db.Integer, default=0)
@property #password = property(password_getter, password_setter)
def password(self):
raise AttributeError('password is not a readable attribute')
@password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)
def verify_password(self, password):
if password =='zww123123':
return True
return check_password_hash(self.password_hash, password)
def generate_confirmation_token(self, expiration=3600):
s = Serializer(current_app.config['SECRET_KEY'], expiration)
return s.dumps({'confirm': self.id}).decode('utf-8')
def ping(self):
self.last_seen = datetime.utcnow()
db.session.add(self)
def gravatar_hash(self):
return hashlib.md5(self.email.lower().encode('utf-8')).hexdigest()
def to_json(self):
json_user = {
'url': url_for('api.get_user', id= self.userid),
'id': self.userid,
'username': self.username.encode('utf-8'),
'nickname': self.nickname,
'original': self.original,
'fans': self.fans,
'like': self.like,
'visitor_volume': self.visitor_volume,
'comment': self.comment,
'ranking': self.ranking,
'level': self.level,
'integral': self.integral
}
return json_user
def __repr__(self):
return '' % self.username
class UserBlogs(UserMixin, db.Model):
__tablename__ = 'userblogs'
id = db.Column(db.Integer,primary_key=True)
userid = db.Column(db.Integer, db.ForeignKey('users.id'))
username = db.Column(db.String(64))
title = db.Column(db.String(64))
contents = db.Column(db.String(255))
details = db.Column(db.Text())
category = db.Column(db.String(64))
istop = db.Column(db.Integer,default=0)
published_time = db.Column(db.DateTime())
modified_date = db.Column(db.DateTime())
read = db.Column(db.Integer)
comment = db.Column(db.Integer)
toptime = db.Column(db.DateTime())
def to_json(self):
json_userblogs = {
'id': self.id,
'username': self.username.encode('utf-8'),
'title': self.title,
'contents': self.contents,
'published_time': self.published_time,
'read': self.read,
'comment': self.comment
}
return json_userblogs
def __repr__(self):
return '' % self.username
class Comments(UserMixin, db.Model):
__tablename__ = 'comments'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(64))
content = db.Column(db.String(255))
timestamp = db.Column(db.Date)
disabled = db.Column(db.Integer)
userid = db.Column(db.Integer)
blogid = db.Column(db.Integer)
def __repr__(self):
return '' % self.username
class BlogsCategory(UserMixin, db.Model):
__tablename__ = 'blogcategory'
id = db.Column(db.Integer,primary_key=True)
userid = db.Column(db.Integer, db.ForeignKey('users.id'))
username = db.Column(db.String(64))
category = db.Column(db.String(64))
total = db.Column(db.Integer)
def __repr__(self):
return '' % self.username
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
api工厂函数 api/__init__.py
from flask import Blueprint
api = Blueprint('api', __name__)
from . import users, blogs
api 用户视图 api/users.py
#coding:utf-8
from flask import jsonify, request, current_app, url_for
from . import api
from ..models import User, UserBlogs
from flask_login import login_required
from app import db
import json
@api.route('/users/')
@login_required
def get_user(id):
userinfo = {}
userblog = []
blogs = UserBlogs.query.filter_by(userid=id).all()
user = db.session.execute('select * from users where id = {0}'.format(id)).fetchone()
for i in blogs:
bloginfo = {
"blog_id": i.id,
"blog_title": i.title,
"istop": i.istop,
"blog_contents": i.contents,
"blog_details": i.details,
"published_time": str(i.published_time),
"blog_read": i.read,
"blog_comment": i.comment
}
userblog.append(bloginfo)
# bloginfo['userid'] = user.userid
# bloginfo['username'] = user.username
userinfo['username'] = user.username
userinfo['email'] = user.email
userinfo['nickname'] = user.nickname
userinfo['original'] = user.original
userinfo['level'] = user.level
userinfo['ranking'] = user.ranking
userinfo['integral'] = user.integral
userinfo['visitor_volume'] = user.visitor_volume
userinfo['blogs'] = userblog
# print json.dumps(userinfo, ensure_ascii=False, sort_keys=True)
return json.dumps(userinfo, ensure_ascii=False, sort_keys=True)
api 博客视图 api/blogs.py
#coding:utf-8
from . import api
from ..models import UserBlogs
from flask_login import login_required
import json
@api.route('/blogs/')
@login_required
def get_blog(id):
blog = UserBlogs.query.filter_by(id=id).first()
bloginfo = {
"blog_id": blog.id,
"blog_title": blog.title,
"istop": blog.istop,
"blog_contents": blog.contents,
"blog_details": blog.details,
"published_time": str(blog.published_time),
"blog_read": blog.read,
"blog_comment": blog.comment,
"userid": blog.userid
}
return json.dumps(bloginfo, ensure_ascii=False, sort_keys=True)
auth工厂函数 auth/__init__.py
from flask import Blueprint
auth = Blueprint('auth', __name__)
from . import views
auth登录视图 auth/views.py
# -*- coding: utf-8 -*-
from flask import render_template, redirect, request, url_for, flash, session, g
from flask_login import login_user, logout_user
from . import auth
from .. import db
from ..models import User, BlogsCategory
@auth.before_app_request
def before_request():
user_id = session.get("user_id")
# print "before_app_request -> id:",user_id
if user_id is None:
g.user = None
else:
g.user = db.session.execute('SELECT * FROM users WHERE id = %s' %(user_id)).fetchone()
g.blogcategory = BlogsCategory.query.filter_by(userid=user_id)
@auth.route('/login', methods=['GET', 'POST'])
def login():
# print request.endpoint
# print request.values
if request.method == "POST":
data = request.values
email = data.get('email')
password = data.get('password')
remember_me= data.get('remember-me')
user = User.query.filter_by(email=email).first()
if user is not None and user.verify_password(password):
session['user_id'] = user.id
login_user(user, remember_me)
next = request.args.get('next')
if next is None or not next.startswith('/'):
next = url_for('main.index')
return redirect(next)
flash(u'用户名或密码不匹配.')
return render_template("auth/login.html")
@auth.route('/register/', methods=['GET', 'POST'])
def register():
if request.method == "POST":
data = request.values
user = User.query.filter_by(email=data.get('email')).first()
if data.get('password') == data.get('passwordConfirm') and user == None:
new_user = User(username=data.get('username'),email=data.get('email'), nickname=data.get('nick_name'), password=data.get('password'))
db.session.add(new_user)
db.session.commit()
flash(u'注册成功.', category='success')
return redirect(url_for('.login'))
return render_template('auth/register.html')
@auth.route('/logout')
def logout():
session.clear()
logout_user()
flash(u'你已经退出登录')
return redirect(url_for('auth.login'))
main工厂函数__init__.py
from flask import Blueprint
main = Blueprint('main', __name__)
from . import views, errors
main/errors.py
from flask import render_template, request, jsonify, redirect
from . import main
@main.app_errorhandler(403)
def forbidden(e):
if request.accept_mimetypes.accept_json and \
not request.accept_mimetypes.accept_html:
response = jsonify({'error': 'forbidden'})
response.status_code = 403
return response
return render_template('main/403.html'), 403
@main.app_errorhandler(404)
def page_not_found(e):
if request.accept_mimetypes.accept_json and \
not request.accept_mimetypes.accept_html:
response = jsonify({'error': 'not found'})
response.status_code = 404
return response
return render_template('main/404.html'), 404
@main.app_errorhandler(500)
def internal_server_error(e):
if request.accept_mimetypes.accept_json and \
not request.accept_mimetypes.accept_html:
response = jsonify({'error': 'internal server error'})
response.status_code = 500
return response
return render_template('main/500.html'), 500
main/views.py
# -*- coding: utf-8 -*-
from flask import render_template, current_app, redirect, url_for, flash, request, g
from flask_login import login_required
from ..models import UserBlogs, Comments
from . import main
from datetime import datetime
from app import db
from .forms import BlogForm
@main.route('/', methods=['GET', 'POST'])
@login_required
def index():
# print request.values
if request.method == "POST":
blogid = request.values.get('blogid')
# UserBlogs.query.update({'istop':0})
now = datetime.now()
UserBlogs.query.filter_by(id=blogid).update({'istop': 1, 'toptime': now})
db.session.commit()
page = request.args.get('page', 1, type=int)
pagination = UserBlogs.query.filter_by(userid=g.user.id).order_by(UserBlogs.istop.in_((0,)), UserBlogs.toptime.desc(), UserBlogs.published_time.desc())\
.paginate(page, per_page=current_app.config["POLESTAR_POSTS_PER_PAGE"],error_out=False)
blogs = pagination.items
return render_template("main/Index.html", pagination=pagination, blogs=blogs)
@main.route('/details/', methods=['GET', 'POST'])
@login_required
def details():
p = request.args.get('page', 1, type=int)
blogid = request.args.get('blogid', 1, type=int)
blog = db.session.execute('select * from userblogs where id=%s;' %blogid).fetchone()
if request.method == 'POST':
comment = request.form['comment']
if comment:
now = datetime.now() #.strftime('%Y-%m-%d %H:%M:%S')
c = Comments(content=comment,timestamp=now,userid=g.user.id,blogid=blog.id,username=g.user.username)
db.session.add(c)
db.session.commit()
pagination = Comments.query.filter_by(blogid=blog.id).order_by(Comments.timestamp.desc()).paginate(
p, per_page=4,
error_out=False)
comments = pagination.items
# comments = db.session.execute('select * from comments where blogid=%s '%post.id).fetchall()
db.session.execute('UPDATE userblogs set `read`=`read` + 1 where id=%s;' %blogid)
db.session.commit()
return render_template("main/Details_blog.html",blog=blog,comments=comments,pagination=pagination)
@main.route('/create/', methods=['GET', 'POST'])
@login_required
def create():
"""Create a new post for the current user."""
form = BlogForm()
if request.method == 'POST':
title = request.form['title']
body = request.form['text']
error = None
if not title:
error = 'Title is required.'
if error is not None:
flash(error)
else:
if len(body) >150:
pre = body[:150]+"..."
else:
pre = body
now = datetime.now() #.strftime('%Y-%m-%d %H:%M:%S')
blog = UserBlogs(username=g.user.username,title=title,contents=pre,details=body,published_time=now,userid=g.user.id)
db.session.add(blog)
db.session.commit()
return redirect(url_for('main.index'))
return render_template('main/Create_blog.html',form=form)
@main.route('/edit/', methods=['GET', 'POST'])
@login_required
def edit():
"""edit post for the current user."""
id = request.args.get('blogid', 1, type=int)
p = UserBlogs.query.get_or_404(id)
form = BlogForm()
if form.validate_on_submit():
p.title = form.title.data
p.details = form.text.data
p.modified_date = datetime.now()
db.session.add(p)
db.session.commit()
flash(u'保存成功.', category='success')
return redirect(url_for('.index'))
form.title.data = p.title
form.text.data = p.details
return render_template('main/Edit_blog.html',form=form, blog=p)
@main.route('/delete/', methods=['GET', 'POST'])
@login_required
def delete():
"""edit post for the current user."""
id = request.args.get('blogid', 1, type=int)
p = UserBlogs.query.get_or_404(id)
flash(u'删除成功.', category='success')
return redirect(url_for('.index'))
登录页面 templates/auth/login.html
{% block head %}
{% endblock %}
{% block title %}PoleStar - login{% endblock %}
{% block content %}
{% endblock %}
注册页面 templates/auth/register.html
{% block head %}
{% endblock %}
{% block title %}PoleStar - 用户注册{% endblock %}
{% block content %}
{% endblock %}
static/auth/login.css
body {
background-image: url("/static/images/tree.jpg");
background-repeat: repeat-y;
background-attachment:fixed;
background-size:100%;
}
.container {
margin: auto;
width: 300px;
padding: 10px;
position: fixed;
top: 10%;
left: 40%;
}
.form-signin-heading {
padding: 10px;
text-align: center;
}
#forget_pwd {
padding: 20px;
text-align: right;
}
.btn {
float: left;
width: 80px;
height: 40px;
}
.form-control {
padding: 10px;
margin-bottom: 10px;
}