Permalink
Browse files

Attempt to integrate formhelpers with pyramid

  • Loading branch information...
tholo committed Sep 21, 2011
0 parents commit 08a59acebe230f08ff3a66147bb42bacd6a5ddaa
@@ -0,0 +1,8 @@
+/.coverage
+/build/
+/cover/
+/coverage.xml
+/data/
+/dist/
+/*.egg-info
+*.pyc
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version
@@ -0,0 +1,2 @@
+include *.txt *.ini *.cfg *.rst
+recursive-include formhelpers2 *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
@@ -0,0 +1,8 @@
+============
+formhelpers2
+============
+
+formhelpers2 is an attempt to use Mike Bayer's formhelpers_ with Pyramid_.
+
+.. _formhelpers: http://techspot.zzzeek.org/2008/07/01/better-form-generation-with-mako-and-pylons
+.. _Pyramid: http://pyramid.org
@@ -0,0 +1,51 @@
+[app:main]
+use = egg:formhelpers2
+
+pyramid.reload_templates = true
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.debug_templates = true
+pyramid.default_locale_name = en
+pyramid.includes = pyramid_debugtoolbar
+
+mako.preprocessor = formhelpers2:mako.process_tags
+mako.directories = formhelpers2:templates
+#mako.module_directory = %(here)s/data/templates
+mako.strict_undefined = true
+
+[server:main]
+use = egg:Paste#http
+host = 0.0.0.0
+port = 6543
+
+# Begin logging configuration
+
+[loggers]
+keys = root, formhelpers2
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_formhelpers2]
+level = DEBUG
+handlers =
+qualname = formhelpers2
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
+
+# End logging configuration
@@ -0,0 +1,17 @@
+from pyramid.config import Configurator
+from pyramid.session import UnencryptedCookieSessionFactoryConfig
+
+def main(global_config, **settings):
+ """
+ This function returns a Pyramid WSGI application.
+ """
+
+ my_session_factory = UnencryptedCookieSessionFactoryConfig('formhelpers2')
+ config = Configurator(settings=settings,
+ session_factory=my_session_factory)
+
+ config.add_static_view('static', 'formhelpers2:static')
+
+ config.scan()
+
+ return config.make_wsgi_app()
@@ -0,0 +1,86 @@
+import re
+
+
+class Form(object):
+ class FormContext(object):
+ pass
+
+ def __init__(self, schema, name):
+ self.schema = schema
+ self.name = name
+
+ def validate(self, data):
+ return self.schema.deserialize(data)
+
+ def render(self, data=None, errors=None, context=None, **kw):
+ if not context:
+ context = self.FormContext()
+ if not data:
+ data = self.schema.serialize()
+
+ setattr(context, self.name, dict(data.iteritems()))
+
+ if errors:
+ if hasattr(context, 'errors'):
+ context.errors.update(errors)
+ else:
+ context.errors = errors
+
+ for key, val in kw.items():
+ setattr(context, key, val)
+
+ return context
+
+
+tag_regexp = re.compile(r'<(\/)?%(\w+):(\w+)\s*(.*?)(\/)?>', re.S)
+attr_regexp = re.compile(
+ r"\s*(\w+)\s*=\s*(?:(?<!\\)'(.*?)(?<!\\)'|(?<!\\)\"(.*?)(?<!\\)\")")
+expr_regexp = re.compile(r'\${(.+?)}')
+
+
+def process_tags(source):
+ """Convert tags of the form <nsname:funcname attrs> into a <%call> tag.
+
+ This is a quick regexp approach that can be replaced with a full blown
+ XML parsing approach, if desired.
+
+ """
+ def process_exprs(t):
+ m = re.match(r'^\${(.+?)}$', t)
+ if m:
+ return m.group(1)
+
+ att = []
+
+ def replace_expr(m):
+ att.append(m.group(1))
+ return "%s"
+
+ t = expr_regexp.sub(replace_expr, t)
+ if att:
+ return "'%s' %% (%s)" % (t.replace("'", r"\'"), ",".join(att))
+ else:
+ return "'%s'" % t.replace("'", r"\'")
+
+ def cvt(match):
+ if bool(match.group(1)):
+ return "</%call>"
+
+ ns = match.group(2)
+ fname = match.group(3)
+ attrs = match.group(4)
+
+ attrs = dict([(key, process_exprs(val1 or val2))
+ for key, val1, val2 in attr_regexp.findall(attrs)])
+ args = attrs.pop("args", "")
+
+ attrs = ",".join(["%s=%s" % (key, value)
+ for key, value in attrs.iteritems()])
+
+ if bool(match.group(5)):
+ return """<%%call expr="%s.%s(%s)" args=%s/>""" % (
+ ns, fname, attrs, args)
+ else:
+ return """<%%call expr="%s.%s(%s)" args=%s>""" % (
+ ns, fname, attrs, args)
+ return tag_regexp.sub(cvt, source)
@@ -0,0 +1,21 @@
+body { background-color: #fff; color: #333; }
+
+body, p {
+ font-family: verdana, arial, helvetica, sans-serif;
+ font-size: 12px;
+ line-height: 18px;
+}
+pre {
+ background-color: #eee;
+ padding: 10px;
+ font-size: 11px;
+ line-height: 13px;
+}
+
+a { color: #000; }
+a:visited { color: #666; }
+a:hover { color: #fff; background-color:#000; }
+
+.error-message{
+ color:red;
+}
@@ -0,0 +1,20 @@
+from pyramid.events import BeforeRender
+from pyramid.events import NewRequest
+from pyramid.events import subscriber
+from pyramid.httpexceptions import HTTPForbidden
+
+from webhelpers.html import tags
+
+
+@subscriber(BeforeRender)
+def add_renderer_globals(event):
+ event['h'] = tags
+
+
+@subscriber(NewRequest)
+def csrf_validation(event):
+ request = event.request
+ if request.method == 'POST':
+ token = request.POST.get('_csrf')
+ if token is None or token != request.session.get_csrf_token():
+ raise HTTPForbidden('Cross Site Request Forgery detected')
@@ -0,0 +1,48 @@
+<%namespace name="form" file="/form_tags.mako"/>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Mako Form Helpers</title>
+ <link rel="stylesheet" href="${request.static_url('formhelpers2:static/style.css')}" type="text/css" />
+</head>
+<body>
+
+<h3>Using Mako Helpers</h3>
+
+<%form:form name="comment_form" controller="comment" action="post">
+<div style="display: none;">
+ <input type="hidden" name="_csrf" value="${request.session.get_csrf_token()}" />
+</div>
+<table>
+ <tr>
+ <th colspan="2">Submit your Comment</th>
+ </tr>
+ <tr>
+ <td>Your Name:</td>
+ <td><%form:text name="name"/></td>
+ </tr>
+
+ <tr>
+ <td>How did you hear about this site ?</td>
+ <td>
+ <%form:select name="heard" options="${heard_choices}">
+ <%form:option value="">None</%form:option>
+ </%form:select>
+ </td>
+ </tr>
+
+ <tr>
+ <td>Comment:</td>
+ <td><%form:textarea name="comment"/></td>
+ </tr>
+
+ <tr>
+ <td colspan="2"><%form:submit/></td>
+ </tr>
+</table>
+</%form:form>
+
+</body>
+</html>
Oops, something went wrong.

0 comments on commit 08a59ac

Please sign in to comment.