-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add class specialisations for using WTForms with the frontend toolkit #400
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
8ac5800
Add a mixin that make it easier to use WTForms with frontend toolkit
lfdebrux e637309
Add DM wrappers for the most commonly used WTForms fields
lfdebrux 9a683f6
Add default hints
lfdebrux dde2e98
Add type attribute to form fields
lfdebrux 72116ea
Add DMSelectFieldMixin for making DMRadioField
lfdebrux 7ce10f6
Add widgets for rendering WTForm fields from Jinja
lfdebrux e99deab
Add the ability to suppress question labels on form widgets
lfdebrux 84902c5
Version bump (major)
lfdebrux File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,4 @@ | |
import flask_featureflags # noqa | ||
|
||
|
||
__version__ = '41.2.1' | ||
__version__ = '42.0.0' |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +0,0 @@ | ||
from .fields import EmailField, StripWhitespaceStringField | ||
from .filters import strip_whitespace | ||
from .helpers import get_errors_from_wtform, remove_csrf_token | ||
from .validators import EmailValidator | ||
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
''' | ||
This module includes mixins that are designed to make it easier to use WTForms | ||
with the Digital Marketplace frontend toolkit. | ||
|
||
For example: | ||
|
||
>>> from wtforms import Form, StringField | ||
>>> | ||
>>> # include the mixin in a new class | ||
>>> class DMStringField(DMFieldMixin, StringField): | ||
... pass | ||
>>> | ||
>>> # create a form with our new field class | ||
>>> class TextForm(Form): | ||
... text = DMStringField('Text field', hint='Type text here.') | ||
>>> | ||
>>> form = TextForm() | ||
>>> | ||
>>> # our new field has all the benefits of DMFieldMixin | ||
>>> form.text.name | ||
'text' | ||
>>> form.text.question | ||
'Text field' | ||
>>> form.text.hint | ||
'Type text here.' | ||
|
||
For more examples of these mixins in action, see `dmutils/forms/dm_fields.py`. | ||
|
||
For more about mixins in general, see this `online article`_, | ||
or the very excellent `Python Cookbook`_ by David Beazley. | ||
|
||
.. _online article: | ||
https://zonca.github.io/2013/04/simple-mixin-usage-in-python.html | ||
.. _Python Cookbook: | ||
http://dabeaz.com/cookbook.html | ||
''' | ||
|
||
from copy import copy | ||
|
||
from wtforms.compat import text_type | ||
from wtforms.fields import SelectField | ||
|
||
|
||
class DMFieldMixin: | ||
''' | ||
A mixin designed to make it easier to use WTForms | ||
with the frontend toolkit. The idea is that the | ||
properties mirror the definitions that the toolkit | ||
template macros expect. | ||
|
||
It adds the following features: | ||
- a `hint` property that can be set in the initialiser | ||
- a `question` property that contains the label text | ||
- a `value` property for the data that is displayed | ||
- an `error` property for the field validation error | ||
|
||
Derived classes which include this mixin should have a | ||
subclass of `wtforms.Field` in their base classes. | ||
''' | ||
def __init__(self, label=None, validators=None, hint=None, **kwargs): | ||
super().__init__(label=label, validators=validators, **kwargs) | ||
self.hint = hint or getattr(self.__class__, 'hint', None) | ||
self.type = getattr(self.__class__, 'type', self.type) | ||
|
||
@property | ||
def question(self): | ||
return self.label.text | ||
|
||
@property | ||
def value(self): | ||
return self._value() | ||
|
||
@property | ||
def error(self): | ||
try: | ||
return self.errors[0] | ||
except IndexError: | ||
return None | ||
|
||
|
||
class DMSelectFieldMixin(SelectField): | ||
''' | ||
A Digital Marketplace wrapper for selection fields. | ||
|
||
The `options` argument for the constructor should be a dictionary with | ||
`value`, label`, and `description` keys. | ||
|
||
The `options` attribute is the choices in a format suitable for the | ||
frontend toolkit. | ||
''' | ||
def __init__(self, label=None, validators=None, coerce=text_type, options=None, **kwargs): | ||
super().__init__(label, validators, coerce, **kwargs) | ||
self.options = copy(options) | ||
|
||
@property | ||
def choices(self): | ||
return [(option['value'], option['label']) for option in self.options] if self.options else [] | ||
|
||
@choices.setter | ||
def choices(self, value): | ||
if value is None: | ||
self.options = None | ||
else: | ||
for value, label in value: | ||
self.options.append( | ||
{ | ||
'label': label, | ||
'value': value, | ||
} | ||
) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
insert amazon affiliate link
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also available at all good bookstores 😛