Skip to content
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

Ordered ModelForm, for when you want a submit button at the bottom of... #110

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions wtforms_alchemy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict

import six
import sqlalchemy as sa


from wtforms import Form
from wtforms.form import FormMeta
from wtforms.validators import (
Expand Down Expand Up @@ -314,3 +321,48 @@ class Meta(object):
all_fields_optional = True
only_indexed_fields = True
include_primary_keys = True


class ModelOrderedForm(ModelForm):
"""
Uses field_order attribute to determine position in new field order.

For when you want that submit button at the bottom of your
automatically generated form.

Because Form._fields is an OrderedDict and the non-meta attributes
in the mro get added first the submit button is always first in a
for field in form loop, unless you give it some help.

Example
-------
nav_metadata = MetaData()
Base = declarative_base(metadata=metadata)


class Example(Base):
__tablename__ = 'example'
id = Column(Integer(), primary_key=True)
name = Column(String(256), info={'label': "Name"})
hidden = Column(Boolean(), info={'label': "Hidden"})
active = Column(Boolean(), info={'label': "Active"})

class ExampleForm(OrderedModelForm):
class Meta:
model = Example
submit = SubmitField('Save')
field_order = ('name', 'active', 'hidden', '*')
"""
def __iter__(self):
field_order = getattr(self, 'field_order', None)
if field_order:
temp_fields = OrderedDict()
for name in field_order:
if name == '*':
for key, f in six.iteritems(self._fields):
if key not in field_order:
temp_fields[key] = f
else:
temp_fields[name] = self._fields[name]
self._fields = temp_fields
return iter(six.itervalues(self._fields))