从0开始搭建flask web 程序(1)

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'))




三、模板(bootstrp3.3.7)

登录页面 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 %}



{% for message in get_flashed_messages() %} {{ message }} {% endfor %}
{% 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;
}

 

 

你可能感兴趣的:(flask,python)