Flaskel is a skeleton for all type of Flask application with rest apis or not.
- Application skeleton:
flaskel init --help
- advanced app factory, see:
flaskel.builder.AppBuilder
- support for testing with
flaskel.tester
package - collection of internal ext and external ext well integrated
- collection of custom flask views
- support multiple wsgi server, but gunicorn is well supported
- run app via cli with many options
- better configuration via multiple source: module, yaml (or json), env variables
- better http support for client and server, see:
flaskel.http
Extensions are registered via AppBuilder, see: flaskel.scripts.skeleton.ext
Third parties extensions:
- Flask-APScheduler
- Flask-Caching
- Flask-Cors
- Flask-HTTPAuth
- Flask-JWT
- Flask-Limiter
- Flask-Mail
- Flask-SQLAlchemy
- Flask-PyMongo
My own external extensions:
- Flask-CloudflareRemote (cloudflareRemote)
- Flask-ErrorsHandler (errors_handler)
- Flask-Logify (logify)
- Flask-ResponseBuilder (response_builder)
- Flask-TemplateSupport (template_support)
Internal extensions:
flaskel.ext.crypto.argon.Argon2
(argon2)flaskel.ext.datetime.FlaskDateHelper
(date_helper)flaskel.ext.ipban.FlaskIPBan
(ipban)flaskel.ext.redis.FlaskRedis
(redis)flaskel.ext.useragent.UserAgent
(useragent)flaskel.ext.redis.FlaskRedis
(redis)flaskel.ext.sendmail.ClientMail
(client_mail) extends Flask-Mailflaskel.ext.jobs.APJobs
(scheduler) extends Flask-APSchedulerflaskel.ext.mongo.FlaskMongoDB
(mongo) extends Flask-PyMongoflaskel.ext.healthcheck.health.HealthCheck
(healthcheck), default checks: glances, mongo, redis, sqlalchemy, system, services (http api)
Wrapper extensions:
flaskel.ext.caching.Cache
wraps Flask-Cachingflaskel.ext.limit.RateLimit
wraps Flask-Limiterflaskel.ext.auth.DBTokenHandler
, flaskel.ext.auth.RedisTokenHandler wraps Flask-JWT
Extra extensions:
flaskel.extra.mobile_support.MobileVersionCompatibility
(mobile_version)flaskel.extra.stripe.PaymentHandler
(stripe)
Flaskel comes with useful views for most common apis or simple web controllers:
flaskel.views.base.BaseView
flaskel.views.rpc.JSONRPCView
flaskel.views.template.RenderTemplate
flaskel.views.template.RenderTemplateString
flaskel.views.base.Resource
flaskel.views.resource.CatalogResource
flaskel.views.resource.Restful
flaskel.views.resource.PatchApiView
flaskel.views.proxy.ProxyView
flaskel.views.proxy.ConfProxyView
flaskel.views.proxy.TransparentProxyView
flaskel.views.proxy.JsonRPCProxy
flaskel.views.proxy.SchemaProxyView
flaskel.views.static.StaticFileView
flaskel.views.static.SPAView
flaskel.views.token.BaseTokenAuth
Extra views:
flaskel.extra.apidoc.ApiDocTemplate
flaskel.extra.apidoc.ApiSpecTemplate
flaskel.extra.media.ApiMedia
flaskel.extra.media.GetMedia
flaskel.extra.mobile_support.MobileReleaseView
Flaskel comes with auxiliaries components from sqlalchemy:
- dump schema via cli:
flaskel schema --help
- custom Model class than adds functionalities to all models
class SQLAModel(Model):
def columns(self): ...
def get_one(cls, raise_not_found=True, to_dict=True, *args, **kwargs): ...
def get_list(cls, to_dict=True, restricted=False, order_by=None, page=None, page_size=None, max_per_page=None, *args, **kwargs): ...
def query_collection(cls, params=None, *args, **kwargs): ...
def update(self, attributes): ...
class ConfigProxy: ...
class ExtProxy: ...
from flaskel import webargs
@webargs.query(...)
...
@webargs.payload(...)
...
@webargs.query_paginate()
...
webargs.paginate()
webargs.Field.integer()
webargs.Field.string()
webargs.Field.decimal()
webargs.Field.boolean()
webargs.Field.positive()
webargs.Field.not_negative()
webargs.Field.not_positive()
webargs.Field.negative()
webargs.Field.isodate()
webargs.Field.list_of()
webargs.OptField.integer()
webargs.OptField.string()
webargs.OptField.decimal()
webargs.OptField.boolean()
webargs.OptField.positive()
webargs.OptField.not_negative()
webargs.OptField.not_positive()
webargs.OptField.negative()
webargs.OptField.isodate()
webargs.OptField.list_of()
webargs.ReqField.integer()
webargs.ReqField.string()
webargs.ReqField.decimal()
webargs.ReqField.boolean()
webargs.ReqField.positive()
webargs.ReqField.not_negative()
webargs.ReqField.not_positive()
webargs.ReqField.negative()
webargs.ReqField.isodate()
webargs.ReqField.list_of()
class PayloadValidator:
schemas = SCHEMAS
validator = JSONSchema
@classmethod
def validate(cls, schema, strict=True): ...
There are many configuration keys provided by many sources, the same key in different source are overridden. Source priorities (low to high):
- python module: all defaults flaskel.config
- mapping (dict): via cli from yaml or json file
- python module: via environment variable
APP_CONFIG_FILE
- environment variables: handled via
python-decouple
, so can be stored in .env or settings.ini file
Configuration via env:
DEBUG
: (default: bool = True)TESTING
: (default: bool = DEBUG)APP_NAME
: (default = flaskel)APP_HOST
: (default = 127.0.0.1)APP_PORT
: (default: int = 5000)FLASK_APP
: (default = app:app)SERVER_NAME
: (default = APP_HOST:APP_PORT)FLASK_ENV
: (default = development)LOCALE
: (default = "en_EN.utf8")JWT_ALGORITHM
: (default = "HS512")JWT_ACCESS_TOKEN_EXPIRES
: (default: 1 day)JWT_REFRESH_TOKEN_EXPIRES
: (default: 14 day)TEMPLATES_AUTO_RELOAD
: (default: bool = DEBUG)EXPLAIN_TEMPLATE_LOADING
: (default: bool = False)SEND_FILE_MAX_AGE_DEFAULT
: (default: 1 day)APIDOCS_ENABLED
: (default: bool = True)CONF_PATH
: (default = flaskel/scripts/skeleton/res)SQLALCHEMY_DATABASE_URI
: (default = sqlite:///db.sqlite)REDIS_URL
: (default = mongodb://localhost)REDIS_CONN_TIMEOUT
: (default: float = 0.05)MONGO_URI
: (default = redis://127.0.0.1:6379)MONGO_CONN_TIMEOUT_MS
: (default: int = 100)MONGO_SERVER_SELECTION_TIMEOUT_MS
: (default: int = 100)BASIC_AUTH_USERNAME
: (default = admin)BASIC_AUTH_PASSWORD
: (default = admin)ADMIN_EMAIL
: (default = admin)ADMIN_PASSWORD
: (default = admin)MAIL_DEBUG
: (default: bool = DEBUG)MAIL_SERVER
: (default = sendria.local)MAIL_PORT
: (default: int = 62000)MAIL_USERNAME
: (default: "")MAIL_PASSWORD
: (default: "")MAIL_USE_SSL
: (default: bool = False)MAIL_USE_TLS
: (default: bool = False)MAIL_DEFAULT_SENDER
: (default = admin@mail.com)MAIL_DEFAULT_RECEIVER
: (default = admin@mail.com)MAIL_RECIPIENT
: (default: admin@mail.com)MAIL_TIMEOUT
: (default: int = 60)PREFERRED_URL_SCHEME
: (default = http if FLASK_ENV = development else https)LOG_BUILDER
: (default = text)LOG_APP_NAME
: (default = APP_NAME)LOG_LOGGER_NAME
: (default = FLASK_ENV)LOG_REQ_SKIP_DUMP
: (default = not TESTING)LOG_RESP_SKIP_DUMP
: (default = not TESTING)LOG_RESP_HEADERS
: (default = [])LOG_REQ_HEADERS
: (default = [])CF_STRICT_ACCESS
: (default = False)VERSION_STORE_MAX
: (default = 6)VERSION_CACHE_EXPIRE
: (default = 60)HTTP_PROTECT_BODY
: (default = False)HTTP_DUMP_REQ_BODY
: (default = False)HTTP_DUMP_RESP_BODY
: (default = False)HTTP_SSL_VERIFY
: (default = True)HTTP_TIMEOUT
: (default = 10)USE_X_SENDFILE
: (default = not DEBUG)ENABLE_ACCEL
: (default = True)WSGI_WERKZEUG_LINT_ENABLED
: (default = TESTING)WSGI_WERKZEUG_PROFILER_ENABLED
: (default = TESTING)WSGI_WERKZEUG_PROFILER_FILE
: (default = "profiler.txt")WSGI_WERKZEUG_PROFILER_RESTRICTION
: *(default: list = [0.1])SQLALCHEMY_ECHO
: (default = TESTING)JSONRPC_BATCH_MAX_REQUEST
: (default = 10)IPBAN_ENABLED
: (default = True)IPBAN_KEY_PREFIX
: (default = APP_NAME)IPBAN_KEY_SEP
: (default = /)IPBAN_BACKEND
: (default = local)IPBAN_BACKEND_OPTS
: (default = {})IPBAN_COUNT
: (default = 5)IPBAN_SECONDS
: (default = 3600)IPBAN_NET_WHITELIST
: (default = 127.0.0.0/8)IPBAN_IP_WHITELIST
: (default = 127.0.0.1)IPBAN_STATUS_CODE
: (default = 403)IPBAN_CHECK_CODES
: (default = 404,405,501)RATELIMIT_ENABLED
: (default = not DEBUG)RATELIMIT_HEADERS_ENABLED
: (default = True)RATELIMIT_IN_MEMORY_FALLBACK_ENABLED
: (default = True)RATELIMIT_STORAGE_URL
: (default = REDIS_URL)RATELIMIT_KEY_PREFIX
: (default = APP_NAME)SCHEDULER_AUTO_START
: (default = True)SCHEDULER_API_ENABLED
: (default = False)CACHE_KEY_PREFIX
: (default = APP_NAME)CACHE_REDIS_URL
: (default = REDIS_URL)CACHE_DEFAULT_TIMEOUT
: (default = 1 hour)CACHE_DISABLED
: (default = False)
Static application configuration:
ERROR_PAGE
: (default = "core/error.html")DATABASE_URL
: (default = SQLALCHEMY_DATABASE_URI)SECRET_KEY_MIN_LENGTH
: (default: int = 256)PRETTY_DATE
: (default = "%d %B %Y %I:%M %p")DATE_ISO_FORMAT
: (default = "%Y-%m-%dT%H:%M:%S")JWT_DEFAULT_SCOPE
: (default = None)JWT_DEFAULT_TOKEN_TYPE
: (default = "bearer")JWT_TOKEN_LOCATION
: (default = ["headers", "query_string"])HTTP_DUMP_BODY
: (default: [False, False])ACCEL_BUFFERING
: (default = True)ACCEL_CHARSET
: (default = "utf-8")ACCEL_LIMIT_RATE
: (default = "off")RB_DEFAULT_ACCEPTABLE_MIMETYPES
: (default = ["application/json", "application/xml"])REQUEST_ID_HEADER
: (default = "X-Request-ID")CACHE_TYPE
: (default = "flask_caching.backends.redis")CACHE_OPTIONS
: (dict)CORS_EXPOSE_HEADERS
: (list)RATELIMIT_STORAGE_OPTIONS
: (dict)SCHEDULER_JOBSTORES
: (dict)SCHEDULER_EXECUTORS
: (dict)SCHEDULER_JOB_DEFAULTS
: (dict)LIMITER
: (dict)FAIL
: (default = "1/second")FAST
: (default = "30/minute")MEDIUM
: (default = "20/minute")SLOW
: (default = "10/minute")BYPASS_KEY
: (default = "X-Limiter-Bypass")BYPASS_VALUE
: (default = "bypass-rate-limit")
Extra configurations are optionally loaded via files in folder CONF_PATH
:
APISPEC
: (swagger.yaml)SCHEMAS
: (schemas.yaml)SCHEDULER_JOBS
: (scheduler.yaml)LOGGING
: (log.yaml) if missing, defaultflaskel.utils.logger:LOGGING
is used
Configuration specific for internal extensions:
-
flaskel.ext.crypto.argon.Argon2
ARGON2_ENCODING
: (default = utf-8)ARGON2_TIME_COST
: (default = 3)ARGON2_HASH_LEN
: (default = 32)ARGON2_PARALLELISM
: (default = 4)ARGON2_SALT_LEN
: (default = 16)ARGON2_MEMORY_COST
: (default = 65536) 64 MiBARGON2_PROFILE
: (default = low) allowed low|high
-
flaskel.ext.healthcheck.health.HealthCheck
HEALTHCHECK_ABOUT_LINK
: (default = None)HEALTHCHECK_VIEW_NAME
: (default = healthcheck)HEALTHCHECK_PATH
: (default = /healthcheck)HEALTHCHECK_PARAM_KEY
: (default = checks)HEALTHCHECK_PARAM_SEP
: (default = +)HEALTHCHECK_CONTENT_TYPE
: (default = application/health+json)
-
flaskel.ext.datetime.FlaskDateHelper
DATE_HELPER_COUNTRY
: (default = IT)DATE_HELPER_PROV
: (default = None)DATE_HELPER_STATE
: (default = None)DATE_ISO_FORMAT
: (default = "%Y-%m-%dT%H:%M:%S")DATE_PRETTY
: (default = "%d %B %Y %I:%M %p")
-
flaskel.ext.jobs.APJobs
SCHEDULER_AUTO_START
: (default = False)SCHEDULER_PATCH_MULTITHREAD
: (default = True)SCHEDULER_LOCK_FILE
: (default = .scheduler.lock)
-
flaskel.ext.ipban.FlaskIPBan
IPBAN_ENABLED
: (default = True)IPBAN_KEY_PREFIX
: (default = APP_NAME)IPBAN_KEY_SEP
: (default = /)IPBAN_BACKEND
: (default = local)IPBAN_BACKEND_OPTS
: (default = {})IPBAN_COUNT
: (default = 5)IPBAN_SECONDS
: (default = 3600)IPBAN_NET_WHITELIST
: (default = 127.0.0.0/8)IPBAN_IP_WHITELIST
: (default = 127.0.0.1)IPBAN_STATUS_CODE
: (default = 403)IPBAN_CHECK_CODES
: (default = 404,405,501)
-
flaskel.ext.caching.Caching
CACHE_TYPE
: (default = "flask_caching.backends.redis")CACHE_REDIS_URL
: (default = REDIS_URL)CACHE_DEFAULT_TIMEOUT
: (default = Seconds.hour)CACHE_KEY_PREFIX
: (default = APP_NAME)CACHE_OPTIONS
: (dict) passed to redis client instance
-
flaskel.ext.redis.FlaskRedis
REDIS_URL
: (default = redis://localhost:6379/0)REDIS_OPTS
: (dict) passed to redis client instance
-
flaskel.ext.mongo.FlaskMongoDB
MONGO_URI
: (default = mongodb://localhost)MONGO_OPTS
: (dict) passed to mongodb client instance
-
flaskel.ext.useragent.UserAgent
USER_AGENT_AUTO_PARSE
: (default = False)
-
flaskel.extra.stripe.PaymentHandler (stripe)
STRIPE_SECRET_KEY
:STRIPE_PUBLIC_KEY
:STRIPE_WEBHOOK_SECRET
:STRIPE_DEBUG
: (default = False)STRIPE_DEFAULT_CURRENCY
: (default = eur)STRIPE_API_VERSION
: (default = 2020-08-27)
-
flaskel.extra.mobile_support.MobileVersionCompatibility (mobile_version)
VERSION_STORE_MAX
: (default = 6)VERSION_CACHE_EXPIRE
: (default = 3600)VERSION_CHECK_ENABLED
: (default = True)VERSION_AGENT_HEADER
: (default = X-Agent)VERSION_API_HEADER
: (default = X-Api-Version)VERSION_STORE_KEY
: (default = x_upgrade_needed)VERSION_HEADER_KEY
: (default = X-Mobile-Version)VERSION_UPGRADE_HEADER
: (default = X-Upgrade-Needed)VERSION_AGENTS
: (default = (android, ios))VERSION_SKIP_STATUSES
: (default = (FORBIDDEN, NOT_FOUND, METHOD_NOT_ALLOWED, TOO_MANY_REQUESTS))
-
flaskel.extra.notification.NotificationHandler
FCM_API_KEY
: mandatory if used
-
flaskel.extra.media.service.MediaService
MEDIA
: (dict)ALLOWED_EXTENSIONS
: (default: [png,jpg])UPLOAD_FOLDER
:EXTERNAL_URL
: