Commit f2698add authored by Serge S. Koval's avatar Serge S. Koval

Merge pull request #815 from larkin/remove-hidden-fields

remove not-visible fields from forms
parents 8db79a06 41eca951
......@@ -25,6 +25,13 @@ class BaseRule(object):
self.rule_set = rule_set
return self
@property
def visible_fields(self):
"""
A list of visible fields for the given rule.
"""
raise NotImplementedError()
def __call__(self, form, form_opts=None, field_args={}):
"""
Render rule.
......@@ -68,6 +75,17 @@ class NestedRule(BaseRule):
self.rules = rule_set.configure_rules(self.rules, self)
return super(NestedRule, self).configure(rule_set, parent)
@property
def visible_fields(self):
"""
Return visible fields for all child rules.
"""
visible_fields = []
for rule in self.rules:
for field in rule.visible_fields:
visible_fields.append(field)
return visible_fields
def __iter__(self):
"""
Return rules.
......@@ -111,6 +129,10 @@ class Text(BaseRule):
self.text = text
self.escape = escape
@property
def visible_fields(self):
return []
def __call__(self, form, form_opts=None, field_args={}):
if self.escape:
return self.text
......@@ -168,6 +190,10 @@ class Macro(BaseRule):
return field
@property
def visible_fields(self):
return []
def __call__(self, form, form_opts=None, field_args={}):
"""
Render macro rule.
......@@ -220,6 +246,10 @@ class Container(Macro):
self.child_rule.configure(rule_set, self)
return super(Container, self).configure(rule_set, parent)
@property
def visible_fields(self):
return self.child_rule.visible_fields
def __call__(self, form, form_opts=None, field_args={}):
"""
Render container.
......@@ -258,6 +288,10 @@ class Field(Macro):
super(Field, self).__init__(render_field)
self.field_name = field_name
@property
def visible_fields(self):
return [self.field_name]
def __call__(self, form, form_opts=None, field_args={}):
"""
Render field.
......@@ -345,6 +379,14 @@ class RuleSet(object):
self.view = view
self.rules = self.configure_rules(rules)
@property
def visible_fields(self):
visible_fields = []
for rule in self.rules:
for field in rule.visible_fields:
visible_fields.append(field)
return visible_fields
def convert_string(self, value):
"""
Convert string to rule.
......
......@@ -5,6 +5,7 @@ from flask import (request, redirect, flash, abort, json, Response,
get_flashed_messages)
from jinja2 import contextfunction
from wtforms.fields import HiddenField
from wtforms.fields.core import UnboundField
from wtforms.validators import ValidationError, Required
from flask_admin.babel import gettext
......@@ -685,6 +686,10 @@ class BaseModelView(BaseView, ActionsMixin):
# Form rendering rules
self._refresh_form_rules_cache()
# Process form rules
self._validate_form_class(self._form_edit_rules, self._edit_form_class)
self._validate_form_class(self._form_create_rules, self._create_form_class)
# Primary key
def get_pk_value(self, model):
"""
......@@ -1001,6 +1006,51 @@ class BaseModelView(BaseView, ActionsMixin):
"""
return validate_form_on_submit(form)
def _get_ruleset_missing_fields(self, ruleset, form):
missing_fields = []
if ruleset:
visible_fields = ruleset.visible_fields
for field in form:
if field.name not in visible_fields:
missing_fields.append(field.name)
return missing_fields
def _validate_form_class(self, ruleset, form_class, remove_missing=True):
form_fields = []
for name, obj in iteritems(form_class.__dict__):
if isinstance(obj, UnboundField):
form_fields.append(name)
missing_fields = []
if ruleset:
visible_fields = ruleset.visible_fields
for field_name in form_fields:
if field_name not in visible_fields:
missing_fields.append(field_name)
if missing_fields:
warnings.warn('Fields missing from ruleset: %s' % (','.join(missing_fields)))
if remove_missing:
self._remove_fields_from_form_class(missing_fields, form_class)
def _validate_form_instance(self, ruleset, form, remove_missing=True):
missing_fields = self._get_ruleset_missing_fields(ruleset=ruleset, form=form)
if missing_fields:
warnings.warn('Fields missing from ruleset: %s' % (','.join(missing_fields)))
if remove_missing:
self._remove_fields_from_form_instance(missing_fields, form)
def _remove_fields_from_form_instance(self, field_names, form):
for field_name in field_names:
form.__delitem__(field_name)
def _remove_fields_from_form_class(self, field_names, form_class):
for field_name in field_names:
delattr(form_class, field_name)
# Helpers
def is_sortable(self, name):
"""
......@@ -1477,6 +1527,8 @@ class BaseModelView(BaseView, ActionsMixin):
return redirect(return_url)
form = self.create_form()
if not hasattr(form, '_validated_ruleset') or not form._validated_ruleset:
self._validate_form_instance(ruleset=self._form_create_rules, form=form)
if self.validate_form(form):
if self.create_model(form):
......@@ -1514,6 +1566,8 @@ class BaseModelView(BaseView, ActionsMixin):
return redirect(return_url)
form = self.edit_form(obj=model)
if not hasattr(form, '_validated_ruleset') or not form._validated_ruleset:
self._validate_form_instance(ruleset=self._form_create_rules, form=form)
if self.validate_form(form):
if self.update_model(form, model):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment