zoukankan      html  css  js  c++  java
  • Flask 学习 六 大型程序结构

    pip freeze >requirement.txt 自动生成版本号

    pip install -r requirement.txt 自动下载对应的库

    梳理结构

    config.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import os
    basedir = os.path.abspath(os.path.dirname(__file__))
    class Config:
        SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'  # 可以用来存储框架,扩展,程序等的配置变量
        SQLALCHEMY_COMMIT_ON_TEARDOWN = True  # 每次请求结束后自动提交数据库的变动
        FLASKY_MAIL_SUBJECT_PREFIX= '[Flasky]'
        FLASKY_MAIL_SENDER= 'Flasky Admin <flasky@example.com>'  # 发件人
        FLASKY_ADMIN = os.environ.get('FLASKY_ADMIN')  # 收件人
    
        @staticmethod
        def init_app(app):
            pass
    
    class DevelopmentConfig(Config):
        DEBUG=True
        # 邮件配置
        MAIL_SERVER= 'smtp.qq.com'
        MAIL_PORT = 465
        MAIL_USE_TLS = True
        MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
        MAIL_PASSWORD= os.environ.get('MAIL_PASSWORD')
        SQLALCHEMY_DATABASE_URI= os.environ.get('DEV_DATABASE_URL') or 'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')
    
    class TestingConfig(Config):
        TESTING=True
        SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or 'sqlite:///' + os.path.join(basedir,'data-test.sqlite')
    
    class ProductionConfig(Config):
        SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///' + os.path.join(basedir,'data.sqlite')
    
    config={
        'development':DevelopmentConfig,
        'testing':TestingConfig,
        'production':ProductionConfig,
        'default':DevelopmentConfig
    }
    View Code

    app/__init__.py   使用程序工厂函数

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Flask
    from flask_moment import Moment
    from flask_bootstrap import Bootstrap
    from flask_mail import Mail
    from flask_sqlalchemy import SQLAlchemy
    from config import config
    
    bootstrap = Bootstrap()
    mail =Mail()
    moment = Moment()
    db = SQLAlchemy()
    
    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)
        mail.init_app(app)
        moment.init_app(app)
        db.init_app(app)
        
        # 附加使用蓝本路由和错误页面
        from . import main as main_blueprint
        app.register_blueprint(main_blueprint)
        return app
    View Code

    蓝本中实现路由和自定义错误页面

    创建蓝本 app/main/__init__.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Blueprint
    main = Blueprint('main',__name__)
    from . import views,errors

    注册蓝本 app/__init__.py 

    # 附加使用蓝本路由和错误页面
    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    app/main/error.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import render_template
    from . import main
    
    #主程序的errorhandler
    @main.errorhandler(404)
    def page_not_find(e):
        return render_template('404.html'), 404
    
    @main.errorhandler(500)
    def internal_server_error(e):
        return render_template('500.html'), 500

    main/views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import render_template,session,redirect,url_for,current_app
    from . import main
    from .forms import NameForm
    from .. import db
    from ..models import User
    from ..email import send_mail
    
    # 使用蓝本自定义路由
    @main.route('/', methods=['get', 'post'])
    def index():
        #name = None
        form = NameForm()
        if form.validate_on_submit():
            user = User.query.filter_by(username=form.name.data).first()
            if user is None:
                user = User(username=form.name.data)
                db.session.add(user)
                session['known']=False
                if current_app.config['FLASKY_ADMIN']:
                    send_mail(current_app.config['FLASKY_ADMIN'],'New user','mail/new_user',user=user)
            else:
                session['known'] = True
            session['name']=form.name.data
            form.name.data=''
            return redirect(url_for('.index'))# 蓝本中index函数在main.index下
    return render_template('index.html', name=session.get('name'), form=form, known=session.get('known',False))

    main/forms.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask_wtf import FlaskForm
    from wtforms import StringField, SubmitField
    from wtforms.validators import DataRequired
    
    class NameForm(FlaskForm):
        name = StringField('姓名', validators=[DataRequired()])
        submit = SubmitField('提交')

    app/email.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from threading import Thread
    from flask import render_template,current_app
    from . import mail
    from flask_mail import Message
    def send_async_email(app,msg):
        with app.app_context():
            mail.send(msg)
    
    def send_mail(to,subject,template,**kwargs):
        app = current_app._get_current_object()
        msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject,sender=app.config['FLASKY_MAIL_SENDER'],recipients=[to])
        msg.body=render_template(template + '.txt',**kwargs)
        msg.html = render_template(template + '.html', **kwargs)
        thr = Thread(target=send_async_email,args=[app,msg])
        thr.start()
        return thr
    View Code

    app/models.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from app import db
    class Role(db.Model):
        __tablename__='roles'
        id = db.Column(db.Integer,primary_key=True)
        name = db.Column(db.String(64),unique=True)
        users = db.relationship('User',backref='role',lazy='dynamic')
    
        def __repr__(self):
            return '<Role %r>'% self.name
    
    
    class User(db.Model):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(64), unique=True,index=True)
        role_id=db.Column(db.Integer,db.ForeignKey('roles.id'))
    
        def __repr__(self):
            return '<User %r>' % self.username

    manage.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import os
    from app import create_app,db
    from app.models import User,Role
    from flask_script import Manager,Shell
    from flask_migrate import Migrate,MigrateCommand
    
    app=create_app(os.getenv('FLASK_CONFIG')or 'default')
    manager = Manager(app)
    # 数据库迁移
    migrate = Migrate(app,db)
    manager.add_command('db',MigrateCommand)
    # 集成python shell
    def make_shell_context():
        return dict(app=app, db=db, User=User, Role=Role)
    manager.add_command("shell", Shell(make_context=make_shell_context))
    
    @manager.command
    def test():
        '''启动单元测试'''
        import unittest
        tests=unittest.TestLoader().discover('tests')
        unittest.TextTestRunner(verbosity=2).run(tests)
    
    if __name__ == '__main__':
        manager.run()
    View Code

    requirements.txt

    alabaster==0.7.9
    alembic==0.9.2
    anaconda-client==1.6.0
    anaconda-navigator==1.5
    anaconda-project==0.4.1
    astroid==1.4.9
    astropy==1.3
    attrs==16.3.0
    Automat==0.5.0
    Babel==2.3.4
    backports.shutil-get-terminal-size==1.0.0
    beautifulsoup4==4.5.3
    bitarray==0.8.1
    blaze==0.10.1
    blinker==1.4
    bokeh==0.12.4
    boto==2.45.0
    Bottleneck==1.2.0
    cffi==1.9.1
    chardet==2.3.0
    chest==0.2.3
    click==6.7
    cloudpickle==0.2.2
    clyent==1.2.2
    colorama==0.3.7
    comtypes==1.1.2
    conda==4.3.16
    configobj==5.0.6
    constantly==15.1.0
    contextlib2==0.5.4
    cryptography==1.7.1
    cssselect==1.0.1
    cycler==0.10.0
    Cython==0.25.2
    cytoolz==0.8.2
    dask==0.13.0
    datashape==0.5.4
    decorator==4.0.11
    dill==0.2.5
    Django==1.11
    docutils==0.13.1
    dominate==2.3.1
    et-xmlfile==1.0.1
    fastcache==1.0.2
    Flask==0.12
    Flask-Bootstrap==3.3.7.1
    Flask-Cors==3.0.2
    Flask-Mail==0.9.1
    Flask-Migrate==2.0.3
    Flask-Moment==0.5.1
    Flask-Script==2.0.5
    Flask-SQLAlchemy==2.2
    Flask-WTF==0.14.2
    get==0.0.0
    gevent==1.2.1
    greenlet==0.4.11
    h5py==2.6.0
    HeapDict==1.0.0
    idna==2.2
    imagesize==0.7.1
    incremental==16.10.1
    ipykernel==4.5.2
    ipython==5.1.0
    ipython-genutils==0.1.0
    ipywidgets==5.2.2
    isort==4.2.5
    itsdangerous==0.24
    jdcal==1.3
    jedi==0.9.0
    jieba==0.38
    Jinja2==2.9.4
    jsonschema==2.5.1
    jupyter==1.0.0
    jupyter-client==4.4.0
    jupyter-console==5.0.0
    jupyter-core==4.2.1
    lazy-object-proxy==1.2.2
    llvmlite==0.15.0
    locket==0.2.0
    lxml==3.7.2
    Mako==1.0.6
    MarkupSafe==0.23
    matplotlib==2.0.0
    menuinst==1.4.4
    mistune==0.7.3
    mpmath==0.19
    multipledispatch==0.4.9
    nbconvert==4.2.0
    nbformat==4.2.0
    networkx==1.11
    nltk==3.2.2
    nose==1.3.7
    notebook==4.3.1
    numba==0.30.1
    numexpr==2.6.1
    numpy==1.11.3
    numpydoc==0.6.0
    odo==0.5.0
    olefile==0.44
    openpyxl==2.4.1
    pandas==0.19.2
    parsel==1.1.0
    partd==0.3.7
    path.py==0.0.0
    pathlib2==2.2.0
    patsy==0.4.1
    pep8==1.7.0
    pickleshare==0.7.4
    Pillow==4.0.0
    ply==3.9
    post==0.0.0
    prompt-toolkit==1.0.9
    psutil==5.0.1
    public==0.0.0
    py==1.4.32
    pyasn1==0.1.9
    pyasn1-modules==0.0.8
    pycosat==0.6.1
    pycparser==2.17
    pycrypto==2.6.1
    pycurl==7.43.0
    PyDispatcher==2.0.5
    pyflakes==1.5.0
    Pygments==2.1.3
    pylint==1.6.4
    PyMySQL==0.7.11
    pyOpenSSL==16.2.0
    pyparsing==2.1.4
    pytest==3.0.5
    python-dateutil==2.6.0
    python-editor==1.0.3
    pytz==2016.10
    pywin32==220
    PyYAML==3.12
    pyzmq==16.0.2
    QtAwesome==0.4.3
    qtconsole==4.2.1
    QtPy==1.2.1
    query-string==0.0.0
    queuelib==1.4.2
    request==0.0.0
    requests==2.12.4
    rope-py3k==0.9.4.post1
    scikit-image==0.12.3
    scikit-learn==0.18.1
    scipy==0.18.1
    Scrapy==1.3.3
    seaborn==0.7.1
    service-identity==16.0.0
    setupfiles==0.0.0
    simplegeneric==0.8.1
    singledispatch==3.4.0.3
    six==1.10.0
    snowballstemmer==1.2.1
    sockjs-tornado==1.0.3
    sphinx==1.5.1
    spyder==3.1.2
    SQLAlchemy==1.1.5
    statsmodels==0.6.1
    sympy==1.0
    tables==3.2.2
    toolz==0.8.2
    tornado==4.4.2
    traitlets==4.3.1
    Twisted==17.1.0
    unicodecsv==0.14.1
    visitor==0.1.3
    w3lib==1.17.0
    wcwidth==0.1.7
    Werkzeug==0.11.15
    widgetsnbextension==1.2.6
    win-unicode-console==0.5
    wordcloud==1.3.1
    wrapt==1.10.8
    WTForms==2.1
    xlrd==1.0.0
    XlsxWriter==0.9.6
    xlwings==0.10.2
    xlwt==1.2.0
    zope.interface==4.3.3
    View Code

    单元测试

    test/test_basic.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import unittest
    from flask import current_app
    from app import create_app,db
    
    class BasicTestCase(unittest.TestCase):
        def setUp(self):
            self.app = create_app('testing')
            self.app_context=self.app.app_context()
            self.app_context.push()
            db.create_all()
        def tearDown(self):
            db.session.remove()
            db.drop_all()
            self.app_context.pop()
        def test_app_exists(self):
            self.assertFalse(current_app is None)
        def test_app_is_testing(self):
            self.assertTrue(current_app.config['TESTING'])
    View Code

    单元测试注册到主程序manager.py

    @manager.command
    def test():
        '''启动单元测试'''
        import unittest
        tests=unittest.TestLoader().discover('tests')
        unittest.TextTestRunner(verbosity=2).run(tests)

    1、创建数据库

    python manage.py shell

    from app import db

    db.create_all()

    2、创建数据库迁移

    python hello.py db init # 创建 migrations 文件夹,所有迁移脚本都存放其中

    3、创建迁移脚本

    python manage.py db migrate 

    4、更新数据库

    python manage.py db upgrade

  • 相关阅读:
    输入成绩看等级
    java输入学生成绩
    java基础
    关于session
    关于XML
    Java EE Map
    互联网应用和企业级应用的区别
    Java EE学习目标
    软件工程-来换网-软件度量
    web前端--学习成果
  • 原文地址:https://www.cnblogs.com/Erick-L/p/6882886.html
Copyright © 2011-2022 走看看