Skip to content

Instantly share code, notes, and snippets.

@sophana
Last active Sep 12, 2018
Embed
What would you like to do?
sample single file templateless flask application that demonstrates flask_bootstrap, flask_wtform, flask_nav, flask_login, and dominate
'''
sample single file templateless flask application that demonstrates flask_bootstrap, flask_wtform, flask_nav, flask_login
uses dominate instead of templates
to use: (in virtual env)
pip install dominate Flask Flask-Bootstrap Flask-WTF flask-nav Flask-Login
python sample_dominate.py
'''
from flask import Flask, session, request, redirect, render_template_string, flash
from flask.sessions import SecureCookieSessionInterface
from flask_bootstrap import Bootstrap,bootstrap_find_resource, render_form
from flask_login import LoginManager, UserMixin, login_required, login_user, logout_user , current_user
from flask_wtf import FlaskForm
from wtforms import StringField,PasswordField,SubmitField
from wtforms.validators import DataRequired
import dominate as dom
import dominate.tags as t
from dominate.util import raw
from flask_nav import Nav
from flask_nav.elements import Navbar, View, Subgroup, Link, Text, Separator
from functools import wraps
app = Flask(__name__)
Bootstrap(app)
app.secret_key = "rAxIqk4mMZkc6VYWwndDDCNg5D6q0AUDs11pGENoNoeo3V1SWVebuOO5XizEevDxl3wVQHRDnp7skeoU"
app.session_interface = SecureCookieSessionInterface();
# login form
class LoginForm(FlaskForm):
login = StringField('Login', validators=[DataRequired()])
passwd = PasswordField('Passwd', validators=[DataRequired()])
submit_button = SubmitField('Login')
# dominate tag which has no tag. useful for example to add js script at end of body
class noTag(t.html_tag):
def _render(self, sb, indent_level=1, indent_str=' ', pretty=True, xhtml=False):
pretty = self._render_children(sb, indent_level , indent_str, pretty, xhtml)
## flask form template rendering (render_form is unfortunately not finished)
formTemplate='''
{%% import "bootstrap/wtf.html" as wtf %%}
{{ wtf.quick_form(form, form_type='%s'%s) }}
'''
def renderForm(form, formType='basic', extraArg='') :
return raw(render_template_string(formTemplate%(formType,extraArg),form=form))
### nav
nav=Nav()
nav.init_app(app)
barGroup = Subgroup( # static subgroup
'Docs',
Link('Flask-Bootstrap', 'http://pythonhosted.org/Flask-Bootstrap'),
Link('Flask-AppConfig', 'https://github.com/mbr/flask-appconfig'),
Link('Flask-Debug', 'https://github.com/mbr/flask-debug'),
Separator(),
Text('Bootstrap'),
Link('Getting started', 'https://v4-alpha.getbootstrap.com/getting-started/introduction/'),
Link('Layout', 'https://v4-alpha.getbootstrap.com/layout/overview/'),
Link('Content', 'https://v4-alpha.getbootstrap.com/content/reboot/'),
Link('Components', 'https://v4-alpha.getbootstrap.com/components/alerts/'),
Link('Utilities', 'https://v4-alpha.getbootstrap.com/utilities/borders/'),
Link('About', 'https://v4-alpha.getbootstrap.com/about/history/'),
)
def topBar():
# dynamic nav bar
return Navbar(*(
[ View('Flask-Bootstrap', '.hello')
, View('Dashboard', '.dash')
]
+ [ View('Logout', '.logout')] * current_user.is_authenticated
+ [ Text('Welcome %s'%('guest' if not current_user.is_authenticated else current_user.id))
, barGroup
]
))
## flask_login minimal user class
class User(UserMixin):
def __init__(self,id):
self.id = id
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"
@login_manager.user_loader
def load_user(userid):
return User(userid)
# this is our bootstrap document template
def getDoc() :
doc = dom.document(title="mypage")
with doc.head:
t.meta(name="viewport",content="width=device-width, initial-scale=1.0")
t.link(href=bootstrap_find_resource('css/bootstrap.css', cdn='bootstrap'),rel="stylesheet")
doc.body, doc.bodyEnd = doc.body.add(t.div(_class="container"), noTag(t.comment("bodyEnd")))
with doc.body:
topBar().render()
# TBD: display flash messages
with doc.bodyEnd:
t.script(src=bootstrap_find_resource('jquery.js', cdn='jquery'))
t.script(src=bootstrap_find_resource('js/bootstrap.js', cdn='bootstrap'))
return doc
#decorator that calls our template
def stdDoc(func):
@wraps(func)
def wrap():
doc=getDoc()
with doc.body:
r=func()
if r is not None:
return r
return doc.render()
return wrap
@app.route('/login',methods=['GET','POST'])
@stdDoc
def login():
form = LoginForm(request.form)
if request.method=='POST' and form.validate_on_submit(): # to get error messages to the browser
if form.login.data == form.passwd.data:
user=User(form.login.data)
login_user(user)
flash("Login Ok!")
return redirect(request.args.get("next"))
else:
form.passwd.errors=["wrong password"]
with t.div(_class="jumbotron"):
t.h1("Please login")
t.p("Password must equal to login in this example")
renderForm(form, formType='horizontal')
@app.route("/logout")
def logout():
logout_user() # call logout_user before getDoc to update the navbar
doc=getDoc()
with doc.body:
t.h1("Logout done")
return doc.render()
@app.route("/dash")
@login_required
@stdDoc
def dash():
t.h1("Welcome %s"%current_user.id)
@app.route('/')
@stdDoc
def hello():
t.h1("Welcome!")
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment