Created
January 17, 2014 17:46
-
-
Save danjac/8477954 to your computer and use it in GitHub Desktop.
Integration of wtforms 2 and Pyramid, including CSRF stuff.
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
from webob.multidict import MultiDict | |
from wtforms import Form as BaseForm | |
from wtforms.csrf.core import CSRF as BaseCSRF | |
class Form(BaseForm): | |
def __init__(self, request, formdata=None, *args, **kwargs): | |
self.request = request | |
formdata = formdata or self.request.POST | |
# we need an '_obj' for handling unique validators etc | |
self._obj = kwargs.pop('obj', None) | |
super(Form, self).__init__(formdata, obj=self._obj, *args, **kwargs) | |
def __json__(self, request): | |
return {'errors': self.errors, 'data': self.data} | |
@classmethod | |
def from_json(cls, request, *args, **kwargs): | |
"""Parses from JSON body in request, handy for Angular etc""" | |
return cls(request, MultiDict(request.json_body), *args, **kwargs) | |
def handle(self): | |
""" | |
Handles full form life-cycle. Checks if request method PUT/POST, | |
runs validate, if invalid sets response status to 400 (Bad Request). | |
Typical usage: | |
@view_config(route_name='submit', renderer='submit.mako') | |
def submit(request): | |
form = MyForm(request) | |
if form.handle(): | |
# do whatever | |
return HTTPSeeOther(...) | |
return {'form': form} | |
""" | |
if self.request.method not in ('POST', 'PUT'): | |
return False | |
if self.validate(): | |
return True | |
# 400 Bad request | |
self.request.response.status_int = 400 | |
return False | |
# template helper methods | |
@property | |
def is_multipart(self): | |
for field in self: | |
if field.type == 'FileField': | |
return True | |
return False | |
@property | |
def hidden_fields(self): | |
return [field for field in self | |
if getattr(field.widget, 'input_type', None) == 'hidden'] | |
@property | |
def submit_fields(self): | |
return [field for field in self if field.type == 'SubmitField'] | |
@property | |
def editable_fields(self): | |
non_editable_fields = self.hidden_fields + self.submit_fields | |
return [field for field in self if field not in non_editable_fields] | |
class CSRF(BaseCSRF): | |
def setup_form(self, form): | |
self.request = form.request | |
return super(CSRF, self).setup_form(form) | |
def generate_csrf_token(self, csrf_context): | |
return self.request.session.get_csrf_token() | |
class SecureMeta(object): | |
csrf = True | |
csrf_class = CSRF | |
class SecureForm(Form): | |
"""Hooks in CSRF meta by default""" | |
class Meta(SecureMeta): | |
pass | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment