22
Flask Templates (aka Jinja2) by @alanhamlett

Jinja2 Templates - San Francisco Flask Meetup

Embed Size (px)

Citation preview

Page 1: Jinja2 Templates - San Francisco Flask Meetup

Flask Templates(aka Jinja2)

by @alanhamlett

Page 2: Jinja2 Templates - San Francisco Flask Meetup

Blocks ( templates/common/base.html )

Blocks name parts of your template, and can be re-used in child templates.

<html>

<title>{% block title %}My Website{% endblock %}</title>

<body>

{% block body %}

{% endblock %}

</body>

</html>

Page 3: Jinja2 Templates - San Francisco Flask Meetup

Inheritance ( templates/login.html )

{% extends "common/base.html" %}

{% block title %}super() - Login{% endblock %}

{% block body %}

<form method="POST">

<p><input type="text" name="username" /></p>

<p><input type="password" name="password" /></p>

<p><button type="submit">Login</button></p>

</form>

{% endblock %}

Page 4: Jinja2 Templates - San Francisco Flask Meetup

Variable Scope ( templates/common/base.html )

<html>

<title>{% block title %}My Website{% endblock %}</title>

<body>

{% with %}

{% set variable = "value" %}

{% block body %}

{% endblock %}

{% endwith %}

</body>

</html>

Page 5: Jinja2 Templates - San Francisco Flask Meetup

Variable Scope ( templates/login.html )

{% extends "common/base.html" %}

{% block title %}super() - Login{% endblock %}

{% block body %}

<form method="POST">

<p><input type="hidden" name="variable" value="{{variable}}" /></p>

<p><input type="text" name="username" /></p>

<p><input type="password" name="password" /></p>

<p><button type="submit">Login</button></p>

</form>

{% endblock %}

Page 6: Jinja2 Templates - San Francisco Flask Meetup

Rendering Templates ( __init__.py )

from flask import Flask

app = Flask(__name__)

from flask import render_template

@app.route("/login")

def login():

return render_template('login.html')

if __name__ == "__main__":

app.run()

Page 7: Jinja2 Templates - San Francisco Flask Meetup

Rendering Templates ( __init__.py )

from flask import Flask

app = Flask(__name__)

from . import views

if __name__ == "__main__":

app.run()

Page 8: Jinja2 Templates - San Francisco Flask Meetup

Rendering Templates ( views.py )

from . import app

from flask import render_template

@app.route("/login")

def login():

context = {

'features': [

{'icon': 'free.png', 'name': 'Free'},

{'icon': 'easy.png', 'name': 'Easy'},

{'icon': 'powerful.png', 'name': 'Powerful'},

],

}

return render_template('login.html', **context)

Page 9: Jinja2 Templates - San Francisco Flask Meetup

Rendering Variables ( templates/login.html )

{% extends "common/base.html" %}

{% block title %}super() - Login{% endblock %}

{% block body %}

<h1>Included Features:</h1>

<ul>

{% for feature in features %}

<li><img src="{{STATIC_URL}}img/icons/{{feature.icon}}" /> {{feature.name}}</li>

{% endfor %}

</ul>

<form method="POST">

<p><input type="text" name="username" /></p>

<p><input type="password" name="password" /></p>

<p><button type="submit">Login</button></p>

</form>

{% endblock %}

Page 10: Jinja2 Templates - San Francisco Flask Meetup
Page 11: Jinja2 Templates - San Francisco Flask Meetup

Filters ( templates/login.html )

{% extends "common/base.html" %}

{% block title %}super() - Login{% endblock %}

{% block body %}

<h1>Included Features:</h1>

<ul>

{% for feature in features %}

<li><img src="{{STATIC_URL}}img/icons/{{feature.icon}}" /> {{feature.name|lower}}</li>

{% endfor %}

</ul>

<form method="POST">

<p><input type="text" name="username" /></p>

<p><input type="password" name="password" /></p>

<p><button type="submit">Login</button></p>

</form>

{% endblock %}

Page 12: Jinja2 Templates - San Francisco Flask Meetup

Flask-WTF ( forms.py )

from flask.ext.wtf import Form

from wtforms import StringField, PasswordField

from wtforms.validators import DataRequired, Email, Length

class LoginForm(Form):

username = StringField('name', validators=[DataRequired(), Email()])

username = PasswordField('name', validators=[DataRequired(), Length(min=6)])

Page 13: Jinja2 Templates - San Francisco Flask Meetup

Flask-WTF ( views.py )

from . import app

from .forms import LoginForm

from flask import render_template, request

@app.route("/login", methods=('GET', 'POST'))

def login():

form = LoginForm(request.form)

if request.method == 'POST' and form.validate():

return redirect('/myprofile')

return render_template('login.html', form=form)

Page 14: Jinja2 Templates - San Francisco Flask Meetup

Flask-WTF ( templates/login.html )

{% extends "common/base.html" %}

{% block title %}super() - Login{% endblock %}

{% block body %}

<form method="POST">

<p>Username <input type="text" name="username" value="{{form.data.username or ''}}" /></p>

<p>Password <input type="password" name="password" value="{{form.data.password or ''}}" /></p>

<p><button type="submit">Login</button></p>

</form>

{% endblock %}

Page 15: Jinja2 Templates - San Francisco Flask Meetup

Flask-WTF ( templates/login.html )...

{% block body %}

<form method="POST">

{% for field in form._fields.values() %}

< div class="form-group" >

{{ field.label(class="col-sm-3 control-label") }}

< div class="col-sm-6 col-md-4" >

{{ field(class="form-control") }}

{% for error in field.errors %}

< p>{{error}}</ p>

{% endfor %}

</ div>

</ div>

{% endfor %}

<div class="form-group" >

< div class="col-sm-6 col-md-4 col-sm-offset-3" >

< button type="submit">Login</button>

</ div>

</ div>

</form>

{% endblock %}

...

Page 16: Jinja2 Templates - San Francisco Flask Meetup

Flask-Admin

Page 17: Jinja2 Templates - San Francisco Flask Meetup

Flask-Admin ( admin.py )from . import app

from .models import db, User

from flask.ext.admin import Admin

from flask.ext.admin.contrib.sqla import ModelView

admin = Admin(app)

admin.add_view(ModelView(User, db.session))

Page 18: Jinja2 Templates - San Francisco Flask Meetup

Flask-Admin ( __init__.py )from flask import Flask

app = Flask(__name__)

from . import views

from . import admin

if __name__ == "__main__":

app.run()

Page 19: Jinja2 Templates - San Francisco Flask Meetup

Flask-Admin

Extend these Flask-Admin classes to protect your Admin pages:

● flask.ext.admin.AdminIndexView

● sqla.ModelView

Page 20: Jinja2 Templates - San Francisco Flask Meetup

Flask-Admin ( admin.py )from . import app

from .models import db, User

from flask.ext.admin import Admin, AdminIndexView as UnsafeAdminIndexView, expose

from flask.ext.admin.contrib.sqla import ModelView

class AdminIndexView(UnsafeAdminIndexView):

@expose('/')

def index(self):

if not app.current_user.is_authenticated():

return redirect('/login')

if not app.current_user.is_admin:

abort(403)

return super(AdminIndexView, self).index()

@expose('/login/')

def login_view(self):

return redirect('/login')

@expose('/logout/')

def logout_view(self):

return redirect('/logout')

admin = Admin(app, index_view=AdminIndexView(), template_mode='bootstrap3', base_template='admin/custom_base.html')

admin.add_view(ModelView(User, db.session))

Page 21: Jinja2 Templates - San Francisco Flask Meetup

Flask-Admin ( admin.py )...

class ModelView(sqla.ModelView):

edit_template = 'admin/model/edit.html'

create_template = 'admin/model/create.html'

list_template = 'admin/model/custom_list.html'

def __init__(self, *args, **kwargs):

if 'exclude' in kwargs:

self.form_excluded_columns = kwargs['exclude']

del kwargs['exclude']

if 'show' in kwargs:

self.column_list = kwargs['show']

del kwargs['show']

pass_through = [

'can_create',

'can_edit',

'can_delete',

]

for item in pass_through:

if item in kwargs:

setattr(self, item, kwargs[item])

del kwargs[item]

super(ModelView, self).__init__(*args, **kwargs)

def is_accessible(self):

return app.current_user.is_authenticated() and app.current_user.is_admin

admin.add_view(ModelView(User, db.session, category='Users', exclude=['password', 'heartbeats'], can_delete=False))

...

Page 22: Jinja2 Templates - San Francisco Flask Meetup

Now go build something cool!

Alan Hamlett@alanhamlett on Twitter & GitHub

[email protected]

View this online at

http://slidesha.re/1wfDzrv