Flask-Maple

captcha ,bootstrap,easy login and more flask tips.


License
BSD-3-Clause
Install
pip install Flask-Maple==0.5.6

Documentation

Flask-Maple

https://img.shields.io/badge/pypi-v0.5.5-brightgreen.svg https://img.shields.io/badge/python-3.4-brightgreen.svg https://img.shields.io/badge/license-BSD-blue.svg

安装

To install Flask-Maple:

pip install flask-maple

Or alternatively, you can download the repository and install manually by doing:

git clone git@github.com:honmaple/flask-maple.git
cd flask-maple
python setup.py install

用户系统

flask_maple/auth/model.py 中默认实现了 GroupMixinUserMixin 如果要创建 user 表与 group 表,只需要

from flask_maple.auth.models import UserMixin, GroupMixin

class User(db.Model, UserMixin):
    pass

class Group(db.Model, GroupMixin):
    pass

即可

user 表默认创建以下字段, 可添加更多想要的字段

  • id
  • username
  • password
  • email
  • is_superuser
  • is_confirmed
  • register_time
  • last_login
  • groups

group 表默认创建以下字段

  • id
  • name
  • users
  • parent_group
  • child_groups

权限

使用

from flask_maple.permission.models import PermissionMixin

class Permission(db.Model, PermissionMixin):
    pass

user 表与 group 表可继承 flask_maple.permission.models.UserMixinflask_maple.permission.models.GroupMixin 或者直接使用 flask_maple.auth.models.UserMixinflask_maple.auth.models.GroupMixin

  • 添加权限
    identity = user # or group
    identity.add_perm(
        action,
        resource,
        resource_type='endpoint',
        description=None)
        
  • 删除权限
    identity.remove_perm(
        action,
        resource,
        resource_type='endpoint')
        
  • 检查权限
    identity.has_perm(action, resource, resource_type='endpoint', and_=False)
        

权限缓存

默认权限会从数据库获取, 如果经常使用,可自行添加缓存, 并在添加删除权限后自行对缓存进行操作

class User(db.Model, UserMixin):
    def perm_cache(self,
                   action,
                   resource,
                   resource_type='endpoint',
                   and_=False):
        return

登录

依赖于 flask-login, flask-mail

使用

from flask_maple import auth

auth.init_app(app)

# 或者
from flask_maple.auth.views import Auth

Auth(app)

将会创建 6个 url

  • /login
  • /logout
  • /register
  • /forget
  • /confirm
  • /confirm/<token>

可以自定义登陆,注册,忘记密码页面,以登陆页面为例 (templates/maple/login.html)

{% extends "base/base.html" %}
{%- block content -%}
{% import 'maple/auth.html' as auth %}
<div class="panel panel-primary">
    <div class="panel-heading">
        <a href="{{ url_for('auth.login') }}" style="color:#fff">{{ _('Login')}}</a>
    </div>
    <div class="panel-body">
        {{ auth.login()}}
    </div>
</div>
{% endblock %}

注意事项

登陆与登出默认使用 user.login(remember) , user.logout(), 如果未使用 flask_maple/auth/model.py 中的 UserMixin,则需要自己定义

验证码

使用 Pillow 生成验证码

pip install pillow

使用

from flask_maple import Captcha
captcha = Captcha(app)

# 因为字体可能存在侵权,所以需要指定自己服务器字体, 默认为 /usr/share/fonts/TTF/DejaVuSans.ttf
captcha = Captcha(app, font="")

然后访问 http://127.0.0.1/captcha

配置

CAPTCHA_URL = "The captcha url,default 'captcha'"

错误处理

主要是对发生错误时的页面进行定制(403,404,500)

from flask_maple import Error
error = Error(app)

定制图片源于*flask*官网,侵删

邮箱

依赖于 flask-mail, 区别使用多线程发送

from flask_maple.mail import Mail

mail = Mail(app)
mail.send_email(*args, **kwargs)

此外,还有一个 MailMixin,实现了邮箱验证需要的密钥,

from flask_maple.mail import MailMixin

class User(db.Model, MailMixin):
    pass

print(user.email_token)
print(User.check_email_token(token, max_age=259200))

表单

数据库

像 django 一样使用 flask-sqlalchemy djang orm 与 sqlalchemy 相比,为什么很多人都认为 django orm 更好用,大概就是因为 django orm 更方便

基本查询(已实现)

  • gt
  • lt
  • lte
  • gte
  • contains
  • in
  • exact
  • iexact
  • startswith
  • istartswith
  • iendswith
  • endswith
  • isnull
  • range
  • year
  • month
  • day

示例:

Post.query.filter_by(title__contains = 'sql').all()
Post.query.exclude_by(title__contains = 'sql').all()

关系查询

Post.query.filter_by(tags__name__contains = 'sql').all()

其它

Post.query.filter_by(tags__name__contains = 'sql').or(Post.id == 1,Post.id == 2).all()
Post.query.filter_by(tags__name__contains = 'sql').and(Post.id == 1,Post.id == 2).all()
Post.query.filter_by(tags__name__contains = 'sql').exists()
Post.query.load_only('title')

序列化

sqlalchemy 对象序列化为 json, 使用方法参考于 django rest framework

多个实例

from flask_maple.serializer import Serializer

posts = Post.query.all()
serializer = Serializer(posts)
data = serializer.data

单个实例

post = Post.query.first()
serializer = Serializer(post)
data = serializer.data

排除字段

serializer = Seralizer(post,exclude=['title'])

仅包括字段

serializer = Seralizer(post,include=['title'])

关系查询深度

serializer = Seralizer(post,depth=3)

depth 默认为*2*

额外的字段

class Post(Model):
    ......
    def get_post_count(self):
        return 11

serializer = Serializer(post,extra=['get_post_count'])

自定义

from flask_maple.serializer import Serializer

class PostSerializer(Serializer):
    class Meta:
        include = []
        depth = 2
        include = []
        exclude = []
        extra = ['count']

serializer = PostSerializer(post,include=['title'])

中间件

参考于 django

from flask_maple.middleware import Middleware

app = ...
Middleware(app)

中间件写法(以一个简单的性能测试中间件为例)

class ProfileMiddleware(object):
    def preprocess_request(self):
        pr = cProfile.Profile()
        pr.enable()
        request.pr = pr

    def process_response(self, response):
        pr = request.pr
        pr.disable()
        s = StringIO()
        sortby = 'cumulative'
        ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
        ps.print_stats()
        print(s.getvalue())
        return response

重要 ,需要加入中间件配置

MIDDLEWARE = ["path.to.ProfileMiddleware"]

日志

记录 infoerror 两个日志 level, 使用很简单

from flask_maple.log import Logging

app = ...
Logging(app)

配置文件

LOGGING = {
    'info': 'logs/info.log',   # 记录 info level 的日志,与配置文件同级下的 logs 目录,可修改
    'error': 'logs/error.log', # 记录 error level 的日志
    'send_mail': False,        # 当有错误发生时,是否发送邮件到管理员邮箱
    'toaddrs': [],             # 管理员邮箱,可为多个
    'subject': 'Your Application Failed',
    'formatter': '''
            Message type:       %(levelname)s
            Location:           %(pathname)s:%(lineno)d
            Module:             %(module)s
            Function:           %(funcName)s
            Time:               %(asctime)s

            Message:

            %(message)s
            '''
}

当*send_mail*为 *True*时, 配置依赖于 *flask_mail*的配置(主要是不想写多份)

MAIL_USERNAME
MAIL_PASSWORD
MAIL_SERVER
MAIL_PORT
MAIL_DEFAULT_SENDER

App

创建两个常用的 url

  • /robots.txt
  • /favicon.ico

使用

from flask_maple.app import App

App(app)

此外,因为国际化等原因,可以传递 flask_maple.json.CustomJSONEncoder 给 App

from flask_maple.app import App
from flask_maple.json import CustomJSONEncoder

App(app, json=CustomJSONEncoder)

配置

参考于 django,可以懒加载 blueprint

INSTALLED_APPS = [
    "path.to.blueprint1",
    "path.to.blueprint2",
    {
        "kwargs":{},
        "blueprint":{}
    }
]

Bootstrap

主要是个人经常使用的一些模板,比如 bootstrap 的js,css 文件,分页模板, 上下撑满等 并依赖于 flask-assets ,对 js,css 文件进行压缩

使用

from flask_maple import Bootstrap
bootstrap = Bootstrap(
    app,
    css=('styles/monokai.css', 'styles/mine.css'),
    js=('styles/upload.js', 'styles/forums.js', 'styles/following.js',
        'styles/topic.js'),
    auth=True)

或者

bootstrap = Bootstrap()
bootstrap.init_app(app)

模板

{% extends 'maple/base.html' %}
{% block main -%}
<button class="btn btn-primary">submit</button>
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
{% endblock -%}

配置

AUTHOR_NAME = "This will show you name at html footer"

Redis

默认会加载 rediscluster.StrictRedisCluster ,如果 rediscluster 未安装则加载 redis.StrictRedis

使用

from flask_maple.redis import Redis

redis = Redis(app)

# 像平时使用 redispy 一样使用
print(redis.get(...))

配置

REDSI = {...}