magic-removal: fixed #1330: edit-inline works again on magic-removal. Note that the API will change *substantailly* before we're done (for example, this reintroduces core fields, which suck) but this at least gives us a place to start with.
Many many thanks for Christopher Lenz, my new hero. git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2502 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4e292dabc0
commit
738d9af1e8
|
@ -12,11 +12,5 @@
|
|||
{% admin_field_line bound_field %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div class="item actions">
|
||||
<button class="deletebutton" name="command" value="{{bound_related_object.relation.var_name}}.{{fcw.index}}.delete">Delete</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="collection actions">
|
||||
<button class="addbutton" name="command" value="{{bound_related_object.relation.var_name}}.add">Add</button>
|
||||
</div>
|
||||
</fieldset>
|
|
@ -1,45 +1,43 @@
|
|||
{% load admin_modify %}
|
||||
<fieldset class="module">
|
||||
<h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst }}</h2><table>
|
||||
<thead><tr>
|
||||
{% for fw in bound_related_object.field_wrapper_list %}
|
||||
{% if fw.needs_header %}
|
||||
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst }}</th>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
||||
{% if change %}{% if original_row_needed %}
|
||||
{% if fcw.obj.original %}
|
||||
<tr class="row-label {% cycle row1,row2 %}"><td colspan="{{ num_headers }}"><strong>{{ fcw.obj.original }}</strong></tr>
|
||||
{% endif %}
|
||||
{% endif %}{% endif %}
|
||||
{% if fcw.obj.errors %}
|
||||
<tr class="errorlist"><td colspan="{{ num_headers }}">
|
||||
{{ fcw.obj.html_combined_error_list }}
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr class="{% cycle row1,row2 %}">
|
||||
{% for bound_field in fcw.bound_fields %}
|
||||
{% if not bound_field.hidden %}
|
||||
<td {{ bound_field.cell_class_attribute }}>
|
||||
{% field_widget bound_field %}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if bound_related_object.show_url %}<td>
|
||||
{% if fcw.obj.original %}<a href="/r/{{ fcw.obj.original.content_type_id }}/{{ fcw.obj.original.id }}/">View on site</a>{% endif %}
|
||||
</td>{% endif %}
|
||||
</tr>
|
||||
|
||||
<fieldset class="module editinline">
|
||||
<h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst }}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{% for fw in bound_related_object.field_wrapper_list %}
|
||||
{% if fw.needs_header %}
|
||||
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst }}</th>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan='{{ num_headers }}'>
|
||||
<button class="addlink" name="command" value="{{ bound_related_object.relation.var_name }}.add">
|
||||
Add another {{ bound_related_object.relation.opts.verbose_name }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
||||
<tr class="{% cycle row1,row2 %}{% if fcw.obj.errors %} error{% endif %}">
|
||||
{% for bound_field in fcw.bound_fields %}
|
||||
{% if not bound_field.hidden %}
|
||||
<td {{ bound_field.cell_class_attribute }}>
|
||||
{{ bound_field.html_error_list }}
|
||||
{% field_widget bound_field %}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<td class="controls" >
|
||||
<button class="inline-deletelink" name="command" value="{{ bound_related_object.relation.var_name }}.{{ fcw.index }}.delete">
|
||||
Delete {{ bound_related_object.relation.opts.verbose_name }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endfor %} </table>
|
||||
|
||||
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
||||
{% for bound_field in fcw.bound_fields %}
|
||||
{% if bound_field.hidden %}
|
||||
{% field_widget bound_field %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</fieldset>
|
|
@ -954,6 +954,16 @@ def get_validation_errors(outfile, app=None):
|
|||
except models.FieldDoesNotExist:
|
||||
e.add(opts, '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name)
|
||||
|
||||
# Check core=True, if needed.
|
||||
for related in opts.get_followed_related_objects():
|
||||
try:
|
||||
for f in related.opts.fields:
|
||||
if f.core:
|
||||
raise StopIteration
|
||||
e.add(related.opts, "At least one field in %s should have core=True, because it's being edited inline by %s.%s." % (related.opts.object_name, opts.module_name, opts.object_name))
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
# Check unique_together.
|
||||
for ut in opts.unique_together:
|
||||
for field_name in ut:
|
||||
|
|
|
@ -74,7 +74,7 @@ class Field(object):
|
|||
self.primary_key = primary_key
|
||||
self.maxlength, self.unique = maxlength, unique
|
||||
self.blank, self.null = blank, null
|
||||
self.rel, self.default = rel, default
|
||||
self.core, self.rel, self.default = core, rel, default
|
||||
self.editable = editable
|
||||
self.validator_list = validator_list or []
|
||||
self.prepopulate_from = prepopulate_from
|
||||
|
@ -88,10 +88,6 @@ class Field(object):
|
|||
# Set db_index to True if the field has a relationship and doesn't explicitly set db_index.
|
||||
self.db_index = db_index
|
||||
|
||||
self.deprecated_args = []
|
||||
if core:
|
||||
self.deprecated_args.append('core')
|
||||
|
||||
# Increase the creation counter, and save our local copy.
|
||||
self.creation_counter = Field.creation_counter
|
||||
Field.creation_counter += 1
|
||||
|
@ -219,14 +215,29 @@ class Field(object):
|
|||
params['validator_list'].append(curry(manipulator_validator_unique, self, opts, manipulator))
|
||||
|
||||
# Only add is_required=True if the field cannot be blank. Primary keys
|
||||
# are a special case.
|
||||
params['is_required'] = not self.blank and not self.primary_key
|
||||
# are a special case, and fields in a related context should set this
|
||||
# as False, because they'll be caught by a separate validator --
|
||||
# RequiredIfOtherFieldGiven.
|
||||
params['is_required'] = not self.blank and not self.primary_key and not rel
|
||||
|
||||
# BooleanFields (CheckboxFields) are a special case. They don't take
|
||||
# is_required or validator_list.
|
||||
if isinstance(self, BooleanField):
|
||||
del params['validator_list'], params['is_required']
|
||||
|
||||
# If this field is in a related context, check whether any other fields
|
||||
# in the related object have core=True. If so, add a validator --
|
||||
# RequiredIfOtherFieldsGiven -- to this FormField.
|
||||
if rel and not self.blank and not isinstance(self, AutoField) and not isinstance(self, FileField):
|
||||
# First, get the core fields, if any.
|
||||
core_field_names = []
|
||||
for f in opts.fields:
|
||||
if f.core and f != self:
|
||||
core_field_names.extend(f.get_manipulator_field_names(name_prefix))
|
||||
# Now, if there are any, add the validator to this FormField.
|
||||
if core_field_names:
|
||||
params['validator_list'].append(validators.RequiredIfOtherFieldsGiven(core_field_names, gettext_lazy("This field is required.")))
|
||||
|
||||
# Finally, add the field_names.
|
||||
field_names = self.get_manipulator_field_names(name_prefix)
|
||||
return [man(field_name=field_names[i], **params) for i, man in enumerate(field_objs)]
|
||||
|
@ -239,9 +250,8 @@ class Field(object):
|
|||
Given the full new_data dictionary (from the manipulator), returns this
|
||||
field's data.
|
||||
"""
|
||||
#if rel:
|
||||
# return new_data.get(self.name, [self.get_default()])[0]
|
||||
#else:
|
||||
if rel:
|
||||
return new_data.get(self.name, [self.get_default()])[0]
|
||||
val = new_data.get(self.name, self.get_default())
|
||||
if not self.empty_strings_allowed and val == '' and self.null:
|
||||
val = None
|
||||
|
@ -397,12 +407,12 @@ class DateTimeField(DateField):
|
|||
|
||||
def get_manipulator_new_data(self, new_data, rel=False):
|
||||
date_field, time_field = self.get_manipulator_field_names('')
|
||||
#if rel:
|
||||
# d = new_data.get(date_field, [None])[0]
|
||||
# t = new_data.get(time_field, [None])[0]
|
||||
#else:
|
||||
d = new_data.get(date_field, None)
|
||||
t = new_data.get(time_field, None)
|
||||
if rel:
|
||||
d = new_data.get(date_field, [None])[0]
|
||||
t = new_data.get(time_field, [None])[0]
|
||||
else:
|
||||
d = new_data.get(date_field, None)
|
||||
t = new_data.get(time_field, None)
|
||||
if d is not None and t is not None:
|
||||
return datetime.datetime.combine(d, t)
|
||||
return self.get_default()
|
||||
|
@ -492,7 +502,10 @@ class FileField(Field):
|
|||
upload_field_name = self.get_manipulator_field_names('')[0]
|
||||
if new_data.get(upload_field_name, False):
|
||||
func = getattr(new_object, 'save_%s_file' % self.name)
|
||||
func(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"])
|
||||
if rel:
|
||||
func(new_data[upload_field_name][0]["filename"], new_data[upload_field_name][0]["content"])
|
||||
else:
|
||||
func(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"])
|
||||
|
||||
def get_directory_name(self):
|
||||
return os.path.normpath(datetime.datetime.now().strftime(self.upload_to))
|
||||
|
|
|
@ -418,6 +418,10 @@ class ForeignKey(RelatedField, Field):
|
|||
kwargs['edit_inline'] = kwargs.pop('edit_inline_type')
|
||||
|
||||
kwargs['rel'] = ManyToOne(to, to_field,
|
||||
num_in_admin=kwargs.pop('num_in_admin', 3),
|
||||
min_num_in_admin=kwargs.pop('min_num_in_admin', None),
|
||||
max_num_in_admin=kwargs.pop('max_num_in_admin', None),
|
||||
num_extra_on_change=kwargs.pop('num_extra_on_change', 1),
|
||||
edit_inline=kwargs.pop('edit_inline', False),
|
||||
related_name=kwargs.pop('related_name', None),
|
||||
limit_choices_to=kwargs.pop('limit_choices_to', None),
|
||||
|
@ -427,10 +431,6 @@ class ForeignKey(RelatedField, Field):
|
|||
|
||||
self.db_index = True
|
||||
|
||||
for name in ('num_in_admin', 'min_num_in_admin', 'max_num_in_admin', 'num_extra_on_change'):
|
||||
if name in kwargs:
|
||||
self.deprecated_args.append(name)
|
||||
|
||||
def get_attname(self):
|
||||
return '%s_id' % self.name
|
||||
|
||||
|
@ -501,6 +501,7 @@ class OneToOneField(RelatedField, IntegerField):
|
|||
kwargs['edit_inline'] = kwargs.pop('edit_inline_type')
|
||||
|
||||
kwargs['rel'] = OneToOne(to, to_field,
|
||||
num_in_admin=kwargs.pop('num_in_admin', 0),
|
||||
edit_inline=kwargs.pop('edit_inline', False),
|
||||
related_name=kwargs.pop('related_name', None),
|
||||
limit_choices_to=kwargs.pop('limit_choices_to', None),
|
||||
|
@ -511,10 +512,6 @@ class OneToOneField(RelatedField, IntegerField):
|
|||
|
||||
self.db_index = True
|
||||
|
||||
for name in ('num_in_admin',):
|
||||
if name in kwargs:
|
||||
self.deprecated_args.append(name)
|
||||
|
||||
def get_attname(self):
|
||||
return '%s_id' % self.name
|
||||
|
||||
|
@ -534,6 +531,7 @@ class ManyToManyField(RelatedField, Field):
|
|||
def __init__(self, to, **kwargs):
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', None)
|
||||
kwargs['rel'] = ManyToMany(to, kwargs.pop('singular', None),
|
||||
num_in_admin=kwargs.pop('num_in_admin', 0),
|
||||
related_name=kwargs.pop('related_name', None),
|
||||
filter_interface=kwargs.pop('filter_interface', None),
|
||||
limit_choices_to=kwargs.pop('limit_choices_to', None),
|
||||
|
@ -542,9 +540,6 @@ class ManyToManyField(RelatedField, Field):
|
|||
if kwargs["rel"].raw_id_admin:
|
||||
kwargs.setdefault("validator_list", []).append(self.isValidIDList)
|
||||
Field.__init__(self, **kwargs)
|
||||
for name in ('num_in_admin'):
|
||||
if name in kwargs:
|
||||
self.deprecated_args.append(name)
|
||||
|
||||
if self.rel.raw_id_admin:
|
||||
msg = gettext_lazy('Separate multiple IDs with commas.')
|
||||
|
@ -641,15 +636,17 @@ class ManyToManyField(RelatedField, Field):
|
|||
pass
|
||||
|
||||
class ManyToOne:
|
||||
def __init__(self, to, field_name, edit_inline=False,
|
||||
def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
|
||||
max_num_in_admin=None, num_extra_on_change=1, edit_inline=False,
|
||||
related_name=None, limit_choices_to=None, lookup_overrides=None, raw_id_admin=False):
|
||||
try:
|
||||
to._meta
|
||||
except AttributeError:
|
||||
except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
|
||||
assert isinstance(to, basestring), "'to' must be either a model, a model name or the string %r" % RECURSIVE_RELATIONSHIP_CONSTANT
|
||||
self.to, self.field_name = to, field_name
|
||||
self.edit_inline = edit_inline
|
||||
self.related_name = related_name
|
||||
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
|
||||
self.min_num_in_admin, self.max_num_in_admin = min_num_in_admin, max_num_in_admin
|
||||
self.num_extra_on_change, self.related_name = num_extra_on_change, related_name
|
||||
self.limit_choices_to = limit_choices_to or {}
|
||||
self.lookup_overrides = lookup_overrides or {}
|
||||
self.raw_id_admin = raw_id_admin
|
||||
|
@ -660,11 +657,11 @@ class ManyToOne:
|
|||
return self.to._meta.get_field(self.field_name)
|
||||
|
||||
class OneToOne(ManyToOne):
|
||||
def __init__(self, to, field_name, edit_inline=False,
|
||||
def __init__(self, to, field_name, num_in_admin=0, edit_inline=False,
|
||||
related_name=None, limit_choices_to=None, lookup_overrides=None,
|
||||
raw_id_admin=False):
|
||||
self.to, self.field_name = to, field_name
|
||||
self.edit_inline = edit_inline
|
||||
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
|
||||
self.related_name = related_name
|
||||
self.limit_choices_to = limit_choices_to or {}
|
||||
self.lookup_overrides = lookup_overrides or {}
|
||||
|
@ -672,10 +669,11 @@ class OneToOne(ManyToOne):
|
|||
self.multiple = False
|
||||
|
||||
class ManyToMany:
|
||||
def __init__(self, to, singular=None, related_name=None,
|
||||
def __init__(self, to, singular=None, num_in_admin=0, related_name=None,
|
||||
filter_interface=None, limit_choices_to=None, raw_id_admin=False, symmetrical=True):
|
||||
self.to = to
|
||||
self.singular = singular or None
|
||||
self.num_in_admin = num_in_admin
|
||||
self.related_name = related_name
|
||||
self.filter_interface = filter_interface
|
||||
self.limit_choices_to = limit_choices_to or {}
|
||||
|
|
|
@ -139,6 +139,9 @@ class AutomaticManipulator(forms.Manipulator):
|
|||
|
||||
if child_follow:
|
||||
obj_list = expanded_data[related.var_name].items()
|
||||
if not obj_list:
|
||||
continue
|
||||
|
||||
obj_list.sort(lambda x, y: cmp(int(x[0]), int(y[0])))
|
||||
|
||||
# For each related item...
|
||||
|
@ -187,15 +190,8 @@ class AutomaticManipulator(forms.Manipulator):
|
|||
if param != None:
|
||||
params[f.attname] = param
|
||||
|
||||
# Related links are a special case, because we have to
|
||||
# manually set the "content_type_id" and "object_id" fields.
|
||||
if self.opts.has_related_links and related.opts.module_name == 'relatedlinks':
|
||||
contenttypes_mod = get_module('core', 'contenttypes')
|
||||
params['content_type_id'] = contenttypes_mod.get_object(package__label__exact=self.opts.app_label, python_module_name__exact=self.opts.module_name).id
|
||||
params['object_id'] = new_object.id
|
||||
|
||||
# Create the related item.
|
||||
new_rel_obj = related.opts.get_model_module().Klass(**params)
|
||||
new_rel_obj = related.model(**params)
|
||||
|
||||
# If all the core fields were provided (non-empty), save the item.
|
||||
if all_cores_given:
|
||||
|
|
|
@ -41,6 +41,35 @@ class RelatedObject(object):
|
|||
"""
|
||||
return data # TODO
|
||||
|
||||
def get_list(self, parent_instance=None):
|
||||
"Get the list of this type of object from an instance of the parent class."
|
||||
if parent_instance is not None:
|
||||
attr = getattr(parent_instance, self.get_accessor_name())
|
||||
if self.field.rel.multiple:
|
||||
# For many-to-many relationships, return a list of objects
|
||||
# corresponding to the xxx_num_in_admin options of the field
|
||||
objects = list(attr.all())
|
||||
|
||||
count = len(objects) + self.field.rel.num_extra_on_change
|
||||
if self.field.rel.min_num_in_admin:
|
||||
count = max(count, self.field.rel.min_num_in_admin)
|
||||
if self.field.rel.max_num_in_admin:
|
||||
count = min(count, self.field.rel.max_num_in_admin)
|
||||
|
||||
change = count - len(objects)
|
||||
if change > 0:
|
||||
return objects + [None for _ in range(change)]
|
||||
if change < 0:
|
||||
return objects[:change]
|
||||
else: # Just right
|
||||
return objects
|
||||
else:
|
||||
# A one-to-one relationship, so just return the single related
|
||||
# object
|
||||
return [attr]
|
||||
else:
|
||||
return [None for _ in range(self.field.rel.num_in_admin)]
|
||||
|
||||
def editable_fields(self):
|
||||
"Get the fields in this class that should be edited inline."
|
||||
return [f for f in self.opts.fields + self.opts.many_to_many if f.editable and f != self.field]
|
||||
|
@ -62,6 +91,30 @@ class RelatedObject(object):
|
|||
over[self.field.name] = False
|
||||
return self.opts.get_follow(over)
|
||||
|
||||
def get_manipulator_fields(self, opts, manipulator, change, follow):
|
||||
if self.field.rel.multiple:
|
||||
if change:
|
||||
attr = getattr(manipulator.original_object, self.get_accessor_name())
|
||||
count = attr.count()
|
||||
count += self.field.rel.num_extra_on_change
|
||||
if self.field.rel.min_num_in_admin:
|
||||
count = max(count, self.field.rel.min_num_in_admin)
|
||||
if self.field.rel.max_num_in_admin:
|
||||
count = min(count, self.field.rel.max_num_in_admin)
|
||||
else:
|
||||
count = self.field.rel.num_in_admin
|
||||
else:
|
||||
count = 1
|
||||
|
||||
fields = []
|
||||
for i in range(count):
|
||||
for f in self.opts.fields + self.opts.many_to_many:
|
||||
if follow.get(f.name, False):
|
||||
prefix = '%s.%d.' % (self.var_name, i)
|
||||
fields.extend(f.get_manipulator_fields(self.opts, manipulator, change,
|
||||
name_prefix=prefix, rel=True))
|
||||
return fields
|
||||
|
||||
def __repr__(self):
|
||||
return "<RelatedObject: %s related to %s>" % (self.name, self.field.name)
|
||||
|
||||
|
|
|
@ -131,10 +131,10 @@ class FormWrapper:
|
|||
def fill_inline_collections(self):
|
||||
if not self._inline_collections:
|
||||
ic = []
|
||||
children = self.manipulator.children.items()
|
||||
for rel_obj, child_manips in children:
|
||||
related_objects = self.manipulator.get_related_objects()
|
||||
for rel_obj in related_objects:
|
||||
data = rel_obj.extract_data(self.data)
|
||||
inline_collection = InlineObjectCollection(self.manipulator, rel_obj, child_manips, data, self.error_dict)
|
||||
inline_collection = InlineObjectCollection(self.manipulator, rel_obj, data, self.error_dict)
|
||||
ic.append(inline_collection)
|
||||
self._inline_collections = ic
|
||||
|
||||
|
@ -213,12 +213,11 @@ class FormFieldCollection(FormFieldWrapper):
|
|||
|
||||
class InlineObjectCollection:
|
||||
"An object that acts like a sparse list of form field collections."
|
||||
def __init__(self, parent_manipulator, rel_obj,child_manips, data, errors):
|
||||
def __init__(self, parent_manipulator, rel_obj, data, errors):
|
||||
self.parent_manipulator = parent_manipulator
|
||||
self.rel_obj = rel_obj
|
||||
self.data = data
|
||||
self.errors = errors
|
||||
self.child_manips = child_manips
|
||||
self._collections = None
|
||||
self.name = rel_obj.name
|
||||
|
||||
|
@ -240,7 +239,7 @@ class InlineObjectCollection:
|
|||
|
||||
def __iter__(self):
|
||||
self.fill()
|
||||
return self._collections.values().__iter__()
|
||||
return iter(self._collections.values())
|
||||
|
||||
def items(self):
|
||||
self.fill()
|
||||
|
@ -250,22 +249,25 @@ class InlineObjectCollection:
|
|||
if self._collections:
|
||||
return
|
||||
else:
|
||||
#var_name = self.rel_obj.opts.object_name.lower()
|
||||
cols = {}
|
||||
#orig = hasattr(self.parent_manipulator, 'original_object') and self.parent_manipulator.original_object or None
|
||||
#orig_list = self.rel_obj.get_list(orig)
|
||||
var_name = self.rel_obj.opts.object_name.lower()
|
||||
collections = {}
|
||||
orig = None
|
||||
if hasattr(self.parent_manipulator, 'original_object'):
|
||||
orig = self.parent_manipulator.original_object
|
||||
orig_list = self.rel_obj.get_list(orig)
|
||||
|
||||
for i, manip in enumerate(self.child_manips) :
|
||||
if manip and not manip.needs_deletion:
|
||||
collection = {'original': manip.original_object}
|
||||
for field in manip.fields:
|
||||
errors = self.errors.get(field.field_name, [])
|
||||
for i, instance in enumerate(orig_list):
|
||||
collection = {'original': instance}
|
||||
for f in self.rel_obj.editable_fields():
|
||||
for field_name in f.get_manipulator_field_names(''):
|
||||
full_field_name = '%s.%d.%s' % (var_name, i, field_name)
|
||||
field = self.parent_manipulator[full_field_name]
|
||||
data = field.extract_data(self.data)
|
||||
last_part = field.field_name[field.field_name.rindex('.') + 1:]
|
||||
collection[last_part] = FormFieldWrapper(field, data, errors)
|
||||
errors = self.errors.get(full_field_name, [])
|
||||
collection[field_name] = FormFieldWrapper(field, data, errors)
|
||||
collections[i] = FormFieldCollection(collection)
|
||||
self._collections = collections
|
||||
|
||||
cols[i] = FormFieldCollection(collection)
|
||||
self._collections = cols
|
||||
|
||||
class FormField:
|
||||
"""Abstract class representing a form field.
|
||||
|
|
Loading…
Reference in New Issue