Here are a couple of examples of how to use Formular with different web frameworks.
Note
These examples require Formular 0.2.
Most of this code is unnecessary, however i wanted to write an example which is as close to a real world application as necessary.
As you can see this application uses sessions and passes the path to the form. This allows Formular to protect the form against CSRF attacks, try sending the data multiple times to the server.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #!/usr/bin/env python
# coding: utf-8
"""
werkzeug_example
~~~~~~~~~~~~~~~~
:copyright: 2010 by Formular Team, see AUTHORS for more details.
:license: MIT, see LICENSE for more details.
"""
import sys
import os
sys.path.insert(
0,
os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)
)
from tempfile import gettempdir
from werkzeug import Request, Response
from werkzeug.exceptions import HTTPException
from werkzeug.routing import Map, Rule
from werkzeug.contrib.sessions import FilesystemSessionStore
from formular.forms import HTMLForm
from formular.fields import TextField, PasswordField
from formular.exceptions import ValidationError
class LoginForm(HTMLForm):
username = TextField(label=u"Username", required=True)
password = PasswordField(label=u"Password", required=True)
repeat_password = password.copy(label=u"Repeat password", equals="password")
def validate_context(self):
if self.username.value != u"Horst":
raise ValidationError(u"A user with the given name doesn't exist")
if self.password.value != u"secret password":
raise ValidationError(u"The given password is wrong")
def index(request):
form = LoginForm(action=request.path, session=request.session)
if request.method.upper() == "POST" and form.validate(request.values):
return Response(u"And you logged in for... nothing, isn't it awesome?")
widget = form.as_widget()
return Response(widget.errors.render() + widget.render(),
mimetype="text/html"
)
url_map = Map([
Rule("/", endpoint="index")
])
views = {
"index": index
}
session_store = FilesystemSessionStore(path=gettempdir())
@Request.application
def application(request):
sid = request.cookies.get("session_id")
if sid is None:
request.session = session_store.new()
else:
request.session = session_store.get(sid)
url_adapter = url_map.bind_to_environ(request.environ)
try:
endpoint, values = url_adapter.match()
response = views[endpoint](request, **values)
except HTTPException as response:
pass
if request.session.should_save:
session_store.save(request.session)
response.set_cookie("session_id", request.session.sid)
return response
if __name__ == "__main__":
from werkzeug import run_simple
run_simple("localhost", 8080, application)
|
As bottle has no included session support this application does not use one and is therefore vulnerable for CSRF attacks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #!/usr/bin/env python
# coding: utf-8
# this is only needed to be able to run the example from the source repo
# without installing formular
import sys
import os
sys.path.insert(
0,
os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)
)
from bottle import run, route, request
from formular.forms import HTMLForm
from formular.fields import TextField, PasswordField
from formular.exceptions import ValidationError
class LoginForm(HTMLForm):
username = TextField(label=u"Username", required=True)
password = PasswordField(label=u"Password", required=True)
repeat_password = password.copy(label=u"Repeat Password", equals="password")
def validate_context(self):
# here we would check if the user exists at all and if the password is
# correct.
#
# btw. as ValidationErrors raises by this validator cannot be assigned
# to a specific field we can't use a dl to display the errors, formular
# handles that and displays them in an ul
if self.username.value != u"Horst":
# if you want to get the current locale for translations you can
# access self.translations.locale
raise ValidationError(u"A user with the given name doesn't exist")
if self.password.value != u"secret password":
raise ValidationError(u"The given password is wrong")
@route("/", method="GET")
def index():
return LoginForm().as_widget().render()
@route("/", method="POST")
def post_index():
form = LoginForm()
if form.validate(request.POST):
# form.data now contains all validated data in a dictionary, we could
# use that to login the user or we can access the .value attribute of
# fields as in LoginForm.validate_context
return u"And you logged in for... nothing, isn't it awesome?"
widget = form.as_widget()
return widget.errors.render() + widget.render()
if __name__ == "__main__":
run(host="localhost", port=8080)
|