首页 > 其他 > 详细

Flask项目初始化

时间:2019-05-16 16:03:27      阅读:158      评论:0      收藏:0      [点我收藏+]

数据库实现命令初始化

1.实现命令主脚本

技术分享图片
# coding=utf-8
from functools import wraps
from getpass import getpass
import sys
import os

#执行到这里的时候commands是为空对象
commands = {}


# 工具函数
def check_input_password(password):
    if len(password.strip()) < 6:
        return check_input_password(getpass(密码长度必须大于6位,请重新输入管理员账户密码:))
    password2 = getpass(再次输入:)
    if password == password2.strip():
        return password
    else:
        return check_input_password(getpass(两次输入密码不一致,请重新输入管理员账户密码:))


def check_input_username(username):
    if username.strip():
        return username
    else:
        return check_input_username(input(请输入管理员账户登录名:))


# 注册命令
def registry_command(cmd_str):
    def decorate(func):
        commands[cmd_str] = func

        @wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapper
    return decorate


@registry_command(init_db)
#到这里的时候commands里面添加一个元素
#commands["init_db"]=init_db
def init_db():
    from public import db
    from config import BASE_DIR
    import apps.account.models
    import apps.configuration.models
    import apps.deploy.models
    import apps.assets.models
    import apps.schedule.models
    import apps.setting.models

    user_input = input(是否要初始化数据库,该操作会清空所有数据[y|n]?)
    if user_input.strip() == y:
        db.drop_all()
        db.create_all()
        with open(os.path.join(BASE_DIR, libs, sql, permissions.sql), encoding=utf-8) as f:
            line = f.readline()
            while line:
                if line.startswith(INSERT INTO):
                    db.engine.execute(line.strip())
                line = f.readline()
        print(数据库已初始化成功!)
        user_input = input(是否需要创建管理员账户[y|n]?)
        if user_input.strip() == y:
            create_admin()


@registry_command(create_admin)
def create_admin():
    from apps.account.models import User

    admin = User.query.filter_by(is_supper=True).first()
    if admin:
        user_input = input(已存在管理员账户 <%s>,需要重置密码[y|n]? % admin.username)
        if user_input.strip() == y:
            password = check_input_password(getpass(请输入新的管理员账户密码:))
            admin.password = password
            admin.token_expired = 0
            admin.save()
            print(重置管理员密码成功!)
    else:
        username = check_input_username(input(请输入管理员账户登录名:))
        password = check_input_password(getpass(请输入管理员账户密码:))
        User(username=username, password=password, nickname=管理员, is_supper=True).save()
        print(创建管理员账户成功!)


@registry_command(enable_admin)
def enable_admin():
    from apps.account.models import User

    admin = User.query.filter_by(is_supper=True).first()
    admin.update(is_active=True)
    print(管理员账户状态已修改为启用!)


def print_usage():
    print(‘‘‘
usage: %s <command>

command:
    init_db         初始化数据库
    create_admin    创建管理员账户
    enable_admin    启用管理员账户,用于登录失败次数过多账户被禁用时使用
    ‘‘‘ % sys.argv[0])


if __name__ == __main__:
    #装饰器的作用是在把此模块加载到内存中的时候先
    #把registry_command函数执行了也就是初始化了commands
    if len(sys.argv) == 1:
        print_usage()
        sys.exit(1)
    cmd = sys.argv.pop(0)  #manage.py
    arg1 = sys.argv.pop(0) #init_db
    r_func = commands.get(arg1)
    if callable(r_func):
        r_func(*sys.argv)
    else:
        print(遇到了不可能会出现的错误!)
manage.py
技术分享图片
INSERT INTO account_permissions (id, name, `desc`) VALUES (100, home_view, Dashboard);

-- 用户管理 -> 用户列表
INSERT INTO account_permissions (id, name, `desc`) VALUES (101, account_user_view, 获取用户列表);
INSERT INTO account_permissions (id, name, `desc`) VALUES (102, account_user_add, 添加用户);
INSERT INTO account_permissions (id, name, `desc`) VALUES (103, account_user_edit, 编辑用户);
INSERT INTO account_permissions (id, name, `desc`) VALUES (104, account_user_del, 删除用户);
INSERT INTO account_permissions (id, name, `desc`) VALUES (105, account_user_disable, 禁用用户);
初始表数据

2.统一配置信息模块

技术分享图片
from pytz import timezone
import os

DEBUG = True
TIME_ZONE = timezone(Asia/Shanghai)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
#SQLALCHEMY_DATABASE_URI = ‘mysql+pymysql://root:root@127.0.0.1/testdb‘
SQLALCHEMY_DATABASE_URI = sqlite:/// + os.path.join(BASE_DIR, test.db)
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = False

DOCKER_REGISTRY_SERVER = localhost:5000
DOCKER_REGISTRY_AUTH = {username: user, password: password}
config.py

3.创建数据库连接实例模块

技术分享图片
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config


app = Flask(__name__)

app.config.from_object(config)
db = SQLAlchemy(app)
View Code

4.实现效果

技术分享图片

 

Flask实现api接口调用鉴权

   1.定义一个总体装饰器

技术分享图片
def require_permission(str_code):
    def decorate(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if not g.user.is_supper:
                or_list = [x.strip() for x in str_code.split(|)]
                # print(or_list)     
                #["account_user_view","account_role_view"]
                #接口要求的权限集合
                for or_item in or_list:
                    and_set = {x.strip() for x in or_item.split(&)}
                    #把列表中单项元素放到一个集合中去
                    #or_item.split(‘&‘) 这里的作用是防止把单词给打散了
                    #split(‘&‘) 这里面只需要指定一个单词中不存在的符号就可以了
                    #{"account_user_view"}
                    and_set = {x.strip() for x in or_item}
                    #{’a‘,‘c‘,‘c‘,‘o‘,‘u‘,‘n‘,‘t‘...,‘w‘}
                    # print(and_set)  #{"account_user_view"}
                    if and_set.issubset(g.user.permissions):
                        break
                else:
                    return json_response(message=Permission denied), 403
                #当迭代的对象迭代完并为空时,位于else的子句将执行
                #而如果在for循环中含有break时则直接终止循环,并不会执行else子句
            return func(*args, **kwargs)

        return wrapper

    return decorate
接口装饰器

  2.定义处理对应url的函数

技术分享图片
@blueprint.route(/<int:u_id>, methods=[PUT])
@require_permission(account_user_edit | account_user_disable)
def put(u_id):
    form, error = JsonParser(nickname, is_active,
                             Argument(role_id, type=int, required=False, help=请选择角色),
                             Argument(email, nullable=True),
                             Argument(password, nullable=False, required=False),
                             Argument(mobile, nullable=True)).parse()

    if error is None:
        u_info = User.query.get_or_404(u_id)
        if form.password:
            u_info.password = form.password
        if not u_info.update(**form) and form.password:
            u_info.save()
        return json_response(u_info)
    return json_response(message=error)
View Code

  3.定义无需鉴权的url

技术分享图片
def init_app(app):
    excel.init_excel(app)
    app.before_request(cross_domain_access_before)
    app.before_request(auth_middleware)




def auth_middleware():
    if request.path == /api/account/users/login/ or request.path.startswith(/api/apis/configs/)             or request.path.startswith(/api/apis/files/) or "static" in request.path or "favicon.ico" in request.path or "/" == request.path or "/login" == request.path:
        return None
    token = request.headers.get(X-TOKEN)
    if token and len(token) == 32:
        g.user = User.query.filter_by(access_token=token).first()
        if g.user and g.user.is_active and g.user.token_expired >= time.time():
            g.user.token_expired = time.time() + 8 * 60 * 60
            g.user.save()
            return None
    return json_response(message=Auth fail, please login), 401
View Code

 

Flask蓝图url配置

   1.app的url配置 无需经过蓝图  直接在app对象上进行设置

技术分享图片
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config


app = Flask(__name__)

@app.route("/")
def index():
    return app.send_static_file(index.html)


@app.route("/login", methods=[GET])
def index_login():
    return app.send_static_file(index.html)
View Code

   2.通过蓝图配置接口的url地址

       1.在每个蓝图app目录下的__init__.py中配置一个url访问前缀

技术分享图片
from apps.account import user
from apps.account import role


def register_blueprint(app):
    app.register_blueprint(user.blueprint, url_prefix=/api/account/users)
    app.register_blueprint(role.blueprint, url_prefix=/api/account/roles)
__init__py

       2.在view处理函数中指定最后的url地址   所以蓝图下的每个处理函数对应的url地址由这两个部分拼接组成

技术分享图片
@blueprint.route(/setting/password, methods=[POST])
def setting_password():
    form, error = JsonParser(
        Argument(password, help=请输入原密码),
        Argument(newpassword, help=请输入新密码)
    ).parse()
    if error is None:
        if g.user.verify_password(form.password):
            g.user.password = form.newpassword
            g.user.save()
        else:
            return json_response(message=原密码错误)
    return json_response(message=error)
views

      3.拼接后的url地址为http://127.0.0.1:3000/api/account/users/setting/info

         1./api/account/users  为url_prefix=‘/api/account/users‘

         2./setting/info             为@blueprint.route(‘/setting/info‘)

  

Flask项目初始化

原文:https://www.cnblogs.com/yxh168/p/10858697.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!