FlaskCBV Installation manual
Introduction
FlaskCBV is Alternative Framework for working with flask with the class Based Views approach (CBV)
The platform allows to implement a clear architecture based on the using of all the benefits of this approach;
These framework are made in a style similar to Django:
- to simplify its study
- because the architecture of the Django looks elegant.
We tried to make the minimum loaded wrapper for the flask, which does not require any special dependencies.
Features of use:
Instead of the route decorator to define handlers we are using urls.py with the description of the scheme and with ability:
- using includes
- the splitting of the namespace for each application
As a configuration file for flaskcbv used the "settings" module; There's also a separate settings module is specifically flask;
Dependences:
- setuptools
- Flask
- Werkzeug
- Jinja2
- MarkupSafe
Installation and setup:
-
Install framework using pip:
$ sudo pip install flaskcbv
The required dependencies will be installed automatically.
-
Create a directory of your project:
$ mkdir project; cd project
-
Create project using flaskcbv utility:
$ flaskcbv initproject
The project will be created in the current directory
-
Start server:
$ cd apps; $ python start.py
The server starts by default on port 5555
-
Try the server using your browser or telnet(in a separate shell), for e.g:
$ telnet localhost 5555 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. GET / HTTP/1.0
HTTP/1.0 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 22 server: my WEB Server Date: Fri, 10 Jun 2016 21:57:46 GMT
It works on FlaskCBV! Connection closed by foreign host.
Project is works, have fun:)
THE DIRECTORY STRUCTURE
In the generated project by default there are two directories:
- apps/ - there are placed the applications of project and modules required to run
- settings/ - flaskcbv settings module
Let us consider separately each of the directories:
Directory: settings/
- init.py - this module contains the base settings of the framework
- local.py - this module is included to the init.py, it is necessary for that would allocate the settings concerning the used development instance.
For example:
In init you can set up base settings such as the application set, the default headers and so on; In local.py you can set/override the database connection settings, the paths to templates, etc... Then if you move project to other instance you can change local.py using a Makefile or other method of automatic creating from prototypes; it is convenient to push "init" into the repository.
If desired, the entire directory of settings can be replaced by settings.py, this is not affect to the framework working;
Directory: apps/
-
start.py - it is a runnable program, it is necessary to start the server in test mode. in this program, are automatically assigned port, and absolute path to the project; based on this program you can easily create the front-end wsgi.py
-
project.py - module which creates a flask app using flaskcbv;
-
flaskconfig.py - a module which sets configuration variables of the Flask;
-
urls.py - module which describes the main namespaces and handlers(urls) of the project
Here placed the default app: "main", which makes output on request: "It works on FlaskCBV!"
- main/urls.py - included to the main urls.py module
- main/views.py - the module contains a view mainView, here also sets the template which is used to output to the user.
- main/templates/main/index.tpl - template of "main" application;
For the successful work of application "main" it placed to the settings module in the APPLICATIONS tuple;
Try to play with project, to withdraw its templates and to write any mixins.
Now you can use Flask with CBV approach
Have fun!:)
regards, procool@
FlaskCBV Examples:
Simple implementation of json server:
from flaskcbv.response import Response
from flaskcbv.view.mixins import JSONMixin
from flaskcbv.view import View
class JSONView(JSONMixin, View):
def get_json_indent(self):
return self.__json_indent
def dispatch(self, request, *args, **kwargs):
try: self.__json_indent = int(request.args['json_indent'])
except: self.__json_indent = None
r = super(JSONView, self).dispatch(request, *args, **kwargs)
## Return context as json
return Response(self.get_as_json())
class myJsonView(JSONView):
def get_context_data(self, **kwargs):
return {'some': 'var'}
"""
when processing myJsonView the client will receive:
{
"errno": 0,
"error": "OK",
"details": "",
"some": "var"
}
"""
Example of checking user session (implementation LoginRequiredMixin):
import logging
import werkzeug.exceptions as ex
from flask import request, session, abort
from flaskcbv.view.mixins import JSONMixin, getArgumentMixin
from flaskcbv.response import Response
from .models import Auth
## Mixin with session validate methods:
class AuthedMixin(object):
def test_for_user(self):
## Try to get session from query parameters:
try: session_= self.request.args['session']
except: session_ = None
## Try to get session from flask.session (cookies)
if session_ is None:
try: session_=session['session']
except: session_= None
## No session, return 401:
if session_ is None:
abort(401)
## Check the session, find the user:
try:
request.user = Auth.session(session_)
session['session'] = session_
except Exception as err:
request.user = None
## Check session Mixin
class _LoginRequiredMixin(object):
def prepare(self, *args, **kwargs):
## The only type of exception - abort
self.test_for_user()
## The session was found but it's wrong(or user not found):
if request.user is None:
abort(403)
return super(_LoginRequiredMixin, self).prepare(*args, **kwargs)
class LoginRequiredMixin(_LoginRequiredMixin, AuthedMixin):
pass
Now, mixing in LoginRequiredMixin to any view, before the dispatch we have carried out the test of session
An example of a forwarding context variables to the template:
import logging
import datetime
from flaskcbv.view import TemplateView
from settings import STATIC_URL
## Provide context varialbes from project settings
class defaultSettingsMixin(object):
def get_context_data(self, **kwargs):
context = super(defaultSettingsMixin, self).get_context_data(**kwargs)
context['STATIC_URL'] = STATIC_URL
return context
class myTemplateView(defaultSettingsMixin, TemplateView):
pass
Now, inheriting myTemplateView in context variables STATIC_URL is set from the settings;
Example of creating and using the template tag(jinja extention):
The classes of template tags should be placed into the directory templatetags located in the root directory of the project;*
Create a directory:
$ cd myproject
$ ls
apps assets settings templates
$ mkdir templatetags; cd templatetags
$ touch __init__.py
Let us create, for example, mytags.py in which:
# encoding: utf8
from jinja2 import nodes
from jinja2.ext import Extension
## This extension will return the type of the given attribute any of the specified object
class ObjectAttrTypeExtension(Extension):
## If this attribute is not defined or is False or None, the extension will not be taken into account when running:
enabled=True
tags = set(['attrtype'])
def __init__(self, environment):
super(ListSortedExtension, self).__init__(environment)
# add the defaults to the environment
environment.extend(
fragment_cache_prefix='',
fragment_cache=None
)
def parse(self, parser):
lineno = next(parser.stream).lineno
# now we parse a single expression that is used as cache key.
args = [parser.parse_expression()]
if parser.stream.skip_if('comma'):
args.append(parser.parse_expression())
else:
args.append(nodes.Const(None))
return nodes.CallBlock(self.call_method('_empty', args),
[], [], "").set_lineno(lineno)
def _empty(self, obj, attr, caller):
try:
return "%s" % type(getattr(obj, attr))
except Exception as err:
pass
return u''
At the start flaskcbv will automatically load the tag and it will be available for using in templates; There is an Example:
{% attrtype request, 'method' %}
- returns: "<type 'str'>"
Read more about jinja2 extentions: http://jinja.pocoo.org/docs/dev/extensions/
Example of FlaskCBV Forms:
## Simple form:
from flaskcbv.forms import Form
class myFormClass(Form):
def clean_test_passed(self, val):
## self.cleaned_data['test_passed'] value will be 'passed'
## self.data['test_passed'] value will be val
return 'passed'
def clean_test_error(self, val):
## self.data['test_error'] value will be val
## there is no key 'test_error' in self.cleaned_data
## self.errors['test_error'] will be: 'Some Error' Exception
raise Exception('Some Error')
from flaskcbv.view.crud import FormViewMixin
from flaskcbv.view import TemplateView
class myFormView(FormViewMixin, TemplateView):
template='index/some.tpl'
form_class = myFormClass
## Uncomment this, if you want default redirect:
#form_success_url = '/action/success/'
#form_unsuccess_url = '/action/unsuccess/'
## Custom url for form success action:
#def get_from_success_url(self):
# return "/some/other/success/url"
## Here, on GET client recv's our template, where in context var.: 'form' we can access to cleaned form variables;
## Let's Redefine POST processing:
def post(self, *args, **kwargs):
## Create our form object:
form = self.get_form()
## Check form, this will run form.clean that will start 'clean_ATTR' methods, like in django
if form.validate():
## By default it's a redirect to self.form_success_url or self.get_from_success_url():
return self.form_valid(form)
else:
## By default returns template with 'form' context variable:
return self.form_invalid(form)