Metadata-Version: 2.1
Name: flaskcbv
Version: 1.5.4
Summary: FlaskCBV is Alternative Framework for working with flask with the class Based Views approach (CBV)
Home-page: https://github.com/procool/flaskcbv/
Author: procool
Author-email: ya.procool@ya.ru
License: BSD 2 Clause
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3.8
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Requires-Dist: Flask
Requires-Dist: Werkzeug (==2.0.0)
Requires-Dist: setuptools

# 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:
1. Install framework using pip:
	$ sudo pip install flaskcbv
  The required dependencies will be installed automatically.

2. Create a directory of your project:
	$ mkdir project; cd project

3. Create project using flaskcbv utility:
	$ flaskcbv initproject
  The project will be created in the current directory

4. Start server:
	$ cd apps;
	$ python start.py
  The server starts by default on port 5555

5. 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)




