Created
May 11, 2012 12:21
-
-
Save aanastasiou/2659299 to your computer and use it in GitHub Desktop.
Using Pylon's Deform with Flask
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""A very simple example to show what is required to get the excellent deform module from the Pylon's project to work with Flask. | |
DeForm is a Pylon's module capable of automatically creating HTML forms that conform to a schema of classes defined in Python through the Colander module. The transformation between Schema<-->Form data is handled by another module called Peppercorn. More information about how these three modules work together can be found at: http://docs.pylonsproject.org/projects/deform/en/latest/?awesome | |
Although DeForm is a Pylon's project, it can also operate as a stand-alone module. This Gist contains all the necessary changes to objects provided by Flask so that DeForm can serialize and deserialize data posted through a Flask.Request. | |
The basic thing that this gist is trying to demonstrate is how to derive from a Flask.Request object in order to change the data type of the Flask.Request.form object that stores the data posted by the client to the server. By default, Flask uses a MultiDict into which the order by which the variables are posted by the client is not preserved. Unfortunately, this messes up the so called "markers" that are required by Peppercorn so that certain fields (such as sequences) are delineated (http://docs.pylonsproject.org/projects/peppercorn/en/latest/?awesome). | |
In this gist, i am simply changing the MultiDict of the Request to an OrderedMultiDict which seems to work. However, please note that according to werkzeug's documentation, OrderedMultiDict is at least one order of magnitude slower than MultiDict (http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.OrderedMultiDict). | |
The accompanying html file must be put in a /templates and any additional files in a /static directory as per Flask's default configuration. The index.html file is basic and bare just to demonstrate the key features that need to be present for Deform to handle widget data properly. | |
""" | |
import flask | |
from werkzeug.datastructures import OrderedMultiDict | |
import colander | |
from deform import Form | |
import peppercorn | |
#Deriving from flask.Request | |
class theRequest(flask.Request): | |
parameter_storage_class = OrderedMultiDict #This is the only parameter that is going to be different | |
#Building a very simple "dummy" schema using Colander | |
class simpleRecord(colander.MappingSchema): | |
description = colander.SchemaNode(colander.String(), validator = colander.Length(min = 1,max=50)) | |
amount = colander.SchemaNode(colander.Int()) | |
class dataList(colander.SequenceSchema): | |
item = simpleRecord() | |
#This may seem redundant but is actually required by Deform | |
class topList(colander.MappingSchema): | |
items = dataList() | |
#Creating the flask "application" | |
app = flask.Flask(__name__) | |
#Configuring the application | |
app.request_class = theRequest #This is what actually effects the change of the form object's type | |
#A standard entry point to be served accepting both GET and POST calls. | |
@app.route("/", methods=["POST","GET"]) | |
def index(): | |
if flask.request.method == "POST": | |
#Please note the "multi=True" | |
controlData = peppercorn.parse(flask.request.form.items(multi=True)) | |
#Now just sort the data just to do some kind of processing | |
controlData['items'] = sorted(controlData['items'],key=lambda x:int(x['amount'])) | |
#Now, create the form to be returned to the user according to the schema defined before and populating it with the data that were posted by the user and processed by the application so far. | |
someForm = Form(topList(),buttons=('submit',)).render(controlData) | |
aMess="Processed Data" #Just a string to define a message | |
else: | |
#Just return an empty form | |
someForm = Form(testSchema.topList(),buttons=('submit',)).render() | |
aMess = "You can use this form to sort a list of simple records" | |
return flask.render_template("index.html",theForm = someForm, theMessage = aMess) | |
if __name__=="__main__": | |
app.debug = True; | |
app.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Ultimate Sorter</title> | |
<style> | |
.wrapper{ | |
margin-left:auto; | |
margin-right:auto; | |
width:1024px; | |
height:128; | |
border:think solid grey; | |
font-family:Verdana; | |
} | |
.header{ | |
width:inherit; | |
border-bottom:thin black solid; | |
} | |
.main{ | |
width:inherit; | |
border-bottom:thin black solid; | |
} | |
.footer{ | |
font-size:smaller | |
} | |
.errorBar{ | |
text-align:center; | |
font-weight:bold; | |
font-style:italic; | |
color:white; | |
background-color:red; | |
height:2em; | |
} | |
</style> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<!-- CSS if required--> | |
<link rel="stylesheet" href="/static/form.css" type="text/css" /> | |
<!-- JavaScript deform.js is absolutely essential for the controls to operate properly--> | |
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script> | |
<script type="text/javascript" src="/static/deform.js"></script> | |
</head> | |
<!--deform.load() MUST be called --> | |
<body onload="deform.load()"> | |
<div class="wrapper"> | |
<div class="header"> | |
<h1>Welcome...</h1> | |
<p>Some website</p> | |
</div> | |
<div class="message"> | |
{{theMessage}} | |
</div> | |
<!--Please note the |safe designation in the following line so that "theForm's" content is not escaped --> | |
<div class="main"> | |
{{ theForm |safe}} | |
</div> | |
<div class="footer"> | |
<p>Blah blah</p> | |
</div> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, the code above gives an error: testSchema (line 56) is not declared.