Added name column to all role lists.
[Melange.git] / app / django / forms / models.py
blobacfa9cec3e68ce0d6e58d2daed7670183dee3718
1 """
2 Helper functions for creating Form classes from Django models
3 and database field objects.
4 """
6 from django.utils.encoding import smart_unicode
7 from django.utils.datastructures import SortedDict
8 from django.utils.text import get_text_list, capfirst
9 from django.utils.translation import ugettext_lazy as _
11 from util import ValidationError, ErrorList
12 from forms import BaseForm, get_declared_fields
13 from fields import Field, ChoiceField, IntegerField, EMPTY_VALUES
14 from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput
15 from widgets import media_property
16 from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME
18 try:
19 set
20 except NameError:
21 from sets import Set as set # Python 2.3 fallback
23 __all__ = (
24 'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model',
25 'save_instance', 'form_for_fields', 'ModelChoiceField',
26 'ModelMultipleChoiceField',
30 def save_instance(form, instance, fields=None, fail_message='saved',
31 commit=True, exclude=None):
32 """
33 Saves bound Form ``form``'s cleaned_data into model instance ``instance``.
35 If commit=True, then the changes to ``instance`` will be saved to the
36 database. Returns ``instance``.
37 """
38 from django.db import models
39 opts = instance._meta
40 if form.errors:
41 raise ValueError("The %s could not be %s because the data didn't"
42 " validate." % (opts.object_name, fail_message))
43 cleaned_data = form.cleaned_data
44 for f in opts.fields:
45 if not f.editable or isinstance(f, models.AutoField) \
46 or not f.name in cleaned_data:
47 continue
48 if fields and f.name not in fields:
49 continue
50 if exclude and f.name in exclude:
51 continue
52 f.save_form_data(instance, cleaned_data[f.name])
53 # Wrap up the saving of m2m data as a function.
54 def save_m2m():
55 opts = instance._meta
56 cleaned_data = form.cleaned_data
57 for f in opts.many_to_many:
58 if fields and f.name not in fields:
59 continue
60 if f.name in cleaned_data:
61 f.save_form_data(instance, cleaned_data[f.name])
62 if commit:
63 # If we are committing, save the instance and the m2m data immediately.
64 instance.save()
65 save_m2m()
66 else:
67 # We're not committing. Add a method to the form to allow deferred
68 # saving of m2m data.
69 form.save_m2m = save_m2m
70 return instance
72 def make_model_save(model, fields, fail_message):
73 """Returns the save() method for a Form."""
74 def save(self, commit=True):
75 return save_instance(self, model(), fields, fail_message, commit)
76 return save
78 def make_instance_save(instance, fields, fail_message):
79 """Returns the save() method for a Form."""
80 def save(self, commit=True):
81 return save_instance(self, instance, fields, fail_message, commit)
82 return save
84 def form_for_fields(field_list):
85 """
86 Returns a Form class for the given list of Django database field instances.
87 """
88 fields = SortedDict([(f.name, f.formfield())
89 for f in field_list if f.editable])
90 return type('FormForFields', (BaseForm,), {'base_fields': fields})
93 # ModelForms #################################################################
95 def model_to_dict(instance, fields=None, exclude=None):
96 """
97 Returns a dict containing the data in ``instance`` suitable for passing as
98 a Form's ``initial`` keyword argument.
100 ``fields`` is an optional list of field names. If provided, only the named
101 fields will be included in the returned dict.
103 ``exclude`` is an optional list of field names. If provided, the named
104 fields will be excluded from the returned dict, even if they are listed in
105 the ``fields`` argument.
107 # avoid a circular import
108 from django.db.models.fields.related import ManyToManyField, OneToOneField
109 opts = instance._meta
110 data = {}
111 for f in opts.fields + opts.many_to_many:
112 if not f.editable:
113 continue
114 if fields and not f.name in fields:
115 continue
116 if exclude and f.name in exclude:
117 continue
118 if isinstance(f, ManyToManyField):
119 # If the object doesn't have a primry key yet, just use an empty
120 # list for its m2m fields. Calling f.value_from_object will raise
121 # an exception.
122 if instance.pk is None:
123 data[f.name] = []
124 else:
125 # MultipleChoiceWidget needs a list of pks, not object instances.
126 data[f.name] = [obj.pk for obj in f.value_from_object(instance)]
127 else:
128 data[f.name] = f.value_from_object(instance)
129 return data
131 def fields_for_model(model, fields=None, exclude=None, formfield_callback=lambda f: f.formfield()):
133 Returns a ``SortedDict`` containing form fields for the given model.
135 ``fields`` is an optional list of field names. If provided, only the named
136 fields will be included in the returned fields.
138 ``exclude`` is an optional list of field names. If provided, the named
139 fields will be excluded from the returned fields, even if they are listed
140 in the ``fields`` argument.
142 # TODO: if fields is provided, it would be nice to return fields in that order
143 field_list = []
144 opts = model._meta
145 for f in opts.fields + opts.many_to_many:
146 if not f.editable:
147 continue
148 if fields and not f.name in fields:
149 continue
150 if exclude and f.name in exclude:
151 continue
152 formfield = formfield_callback(f)
153 if formfield:
154 field_list.append((f.name, formfield))
155 return SortedDict(field_list)
157 class ModelFormOptions(object):
158 def __init__(self, options=None):
159 self.model = getattr(options, 'model', None)
160 self.fields = getattr(options, 'fields', None)
161 self.exclude = getattr(options, 'exclude', None)
164 class ModelFormMetaclass(type):
165 def __new__(cls, name, bases, attrs):
166 formfield_callback = attrs.pop('formfield_callback',
167 lambda f: f.formfield())
168 try:
169 parents = [b for b in bases if issubclass(b, ModelForm)]
170 except NameError:
171 # We are defining ModelForm itself.
172 parents = None
173 declared_fields = get_declared_fields(bases, attrs, False)
174 new_class = super(ModelFormMetaclass, cls).__new__(cls, name, bases,
175 attrs)
176 if not parents:
177 return new_class
179 if 'media' not in attrs:
180 new_class.media = media_property(new_class)
181 opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))
182 if opts.model:
183 # If a model is defined, extract form fields from it.
184 fields = fields_for_model(opts.model, opts.fields,
185 opts.exclude, formfield_callback)
186 # Override default model fields with any custom declared ones
187 # (plus, include all the other declared fields).
188 fields.update(declared_fields)
189 else:
190 fields = declared_fields
191 new_class.declared_fields = declared_fields
192 new_class.base_fields = fields
193 return new_class
195 class BaseModelForm(BaseForm):
196 def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
197 initial=None, error_class=ErrorList, label_suffix=':',
198 empty_permitted=False, instance=None):
199 opts = self._meta
200 if instance is None:
201 # if we didn't get an instance, instantiate a new one
202 self.instance = opts.model()
203 object_data = {}
204 else:
205 self.instance = instance
206 object_data = model_to_dict(instance, opts.fields, opts.exclude)
207 # if initial was provided, it should override the values from instance
208 if initial is not None:
209 object_data.update(initial)
210 super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
211 error_class, label_suffix, empty_permitted)
212 def clean(self):
213 self.validate_unique()
214 return self.cleaned_data
216 def validate_unique(self):
217 from django.db.models.fields import FieldDoesNotExist
219 # Gather a list of checks to perform. Since this is a ModelForm, some
220 # fields may have been excluded; we can't perform a unique check on a
221 # form that is missing fields involved in that check.
222 unique_checks = []
223 for check in self.instance._meta.unique_together[:]:
224 fields_on_form = [field for field in check if field in self.fields]
225 if len(fields_on_form) == len(check):
226 unique_checks.append(check)
228 form_errors = []
230 # Gather a list of checks for fields declared as unique and add them to
231 # the list of checks. Again, skip fields not on the form.
232 for name, field in self.fields.items():
233 try:
234 f = self.instance._meta.get_field_by_name(name)[0]
235 except FieldDoesNotExist:
236 # This is an extra field that's not on the ModelForm, ignore it
237 continue
238 # MySQL can't handle ... WHERE pk IS NULL, so make sure we
239 # don't generate queries of that form.
240 is_null_pk = f.primary_key and self.cleaned_data[name] is None
241 if name in self.cleaned_data and f.unique and not is_null_pk:
242 unique_checks.append((name,))
244 # Don't run unique checks on fields that already have an error.
245 unique_checks = [check for check in unique_checks if not [x in self._errors for x in check if x in self._errors]]
247 bad_fields = set()
248 for unique_check in unique_checks:
249 # Try to look up an existing object with the same values as this
250 # object's values for all the unique field.
252 lookup_kwargs = {}
253 for field_name in unique_check:
254 lookup_kwargs[field_name] = self.cleaned_data[field_name]
256 qs = self.instance.__class__._default_manager.filter(**lookup_kwargs)
258 # Exclude the current object from the query if we are editing an
259 # instance (as opposed to creating a new one)
260 if self.instance.pk is not None:
261 qs = qs.exclude(pk=self.instance.pk)
263 # This cute trick with extra/values is the most efficient way to
264 # tell if a particular query returns any results.
265 if qs.extra(select={'a': 1}).values('a').order_by():
266 model_name = capfirst(self.instance._meta.verbose_name)
268 # A unique field
269 if len(unique_check) == 1:
270 field_name = unique_check[0]
271 field_label = self.fields[field_name].label
272 # Insert the error into the error dict, very sneaky
273 self._errors[field_name] = ErrorList([
274 _(u"%(model_name)s with this %(field_label)s already exists.") % \
275 {'model_name': unicode(model_name),
276 'field_label': unicode(field_label)}
278 # unique_together
279 else:
280 field_labels = [self.fields[field_name].label for field_name in unique_check]
281 field_labels = get_text_list(field_labels, _('and'))
282 form_errors.append(
283 _(u"%(model_name)s with this %(field_label)s already exists.") % \
284 {'model_name': unicode(model_name),
285 'field_label': unicode(field_labels)}
288 # Mark these fields as needing to be removed from cleaned data
289 # later.
290 for field_name in unique_check:
291 bad_fields.add(field_name)
293 for field_name in bad_fields:
294 del self.cleaned_data[field_name]
295 if form_errors:
296 # Raise the unique together errors since they are considered
297 # form-wide.
298 raise ValidationError(form_errors)
300 def save(self, commit=True):
302 Saves this ``form``'s cleaned_data into model instance
303 ``self.instance``.
305 If commit=True, then the changes to ``instance`` will be saved to the
306 database. Returns ``instance``.
308 if self.instance.pk is None:
309 fail_message = 'created'
310 else:
311 fail_message = 'changed'
312 return save_instance(self, self.instance, self._meta.fields, fail_message, commit)
314 class ModelForm(BaseModelForm):
315 __metaclass__ = ModelFormMetaclass
317 def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
318 formfield_callback=lambda f: f.formfield()):
319 # HACK: we should be able to construct a ModelForm without creating
320 # and passing in a temporary inner class
321 class Meta:
322 pass
323 setattr(Meta, 'model', model)
324 setattr(Meta, 'fields', fields)
325 setattr(Meta, 'exclude', exclude)
326 class_name = model.__name__ + 'Form'
327 return ModelFormMetaclass(class_name, (form,), {'Meta': Meta,
328 'formfield_callback': formfield_callback})
331 # ModelFormSets ##############################################################
333 class BaseModelFormSet(BaseFormSet):
335 A ``FormSet`` for editing a queryset and/or adding new objects to it.
337 model = None
339 def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
340 queryset=None, **kwargs):
341 self.queryset = queryset
342 defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
343 defaults['initial'] = [model_to_dict(obj) for obj in self.get_queryset()]
344 defaults.update(kwargs)
345 super(BaseModelFormSet, self).__init__(**defaults)
347 def _construct_form(self, i, **kwargs):
348 if i < self._initial_form_count:
349 kwargs['instance'] = self.get_queryset()[i]
350 return super(BaseModelFormSet, self)._construct_form(i, **kwargs)
352 def get_queryset(self):
353 if not hasattr(self, '_queryset'):
354 if self.queryset is not None:
355 qs = self.queryset
356 else:
357 qs = self.model._default_manager.get_query_set()
358 if self.max_num > 0:
359 self._queryset = qs[:self.max_num]
360 else:
361 self._queryset = qs
362 return self._queryset
364 def save_new(self, form, commit=True):
365 """Saves and returns a new model instance for the given form."""
366 return save_instance(form, self.model(), exclude=[self._pk_field.name], commit=commit)
368 def save_existing(self, form, instance, commit=True):
369 """Saves and returns an existing model instance for the given form."""
370 return save_instance(form, instance, exclude=[self._pk_field.name], commit=commit)
372 def save(self, commit=True):
373 """Saves model instances for every form, adding and changing instances
374 as necessary, and returns the list of instances.
376 if not commit:
377 self.saved_forms = []
378 def save_m2m():
379 for form in self.saved_forms:
380 form.save_m2m()
381 self.save_m2m = save_m2m
382 return self.save_existing_objects(commit) + self.save_new_objects(commit)
384 def save_existing_objects(self, commit=True):
385 self.changed_objects = []
386 self.deleted_objects = []
387 if not self.get_queryset():
388 return []
390 # Put the objects from self.get_queryset into a dict so they are easy to lookup by pk
391 existing_objects = {}
392 for obj in self.get_queryset():
393 existing_objects[obj.pk] = obj
394 saved_instances = []
395 for form in self.initial_forms:
396 obj = existing_objects[form.cleaned_data[self._pk_field.name]]
397 if self.can_delete and form.cleaned_data[DELETION_FIELD_NAME]:
398 self.deleted_objects.append(obj)
399 obj.delete()
400 else:
401 if form.changed_data:
402 self.changed_objects.append((obj, form.changed_data))
403 saved_instances.append(self.save_existing(form, obj, commit=commit))
404 if not commit:
405 self.saved_forms.append(form)
406 return saved_instances
408 def save_new_objects(self, commit=True):
409 self.new_objects = []
410 for form in self.extra_forms:
411 if not form.has_changed():
412 continue
413 # If someone has marked an add form for deletion, don't save the
414 # object.
415 if self.can_delete and form.cleaned_data[DELETION_FIELD_NAME]:
416 continue
417 self.new_objects.append(self.save_new(form, commit=commit))
418 if not commit:
419 self.saved_forms.append(form)
420 return self.new_objects
422 def add_fields(self, form, index):
423 """Add a hidden field for the object's primary key."""
424 from django.db.models import AutoField
425 self._pk_field = pk = self.model._meta.pk
426 if pk.auto_created or isinstance(pk, AutoField):
427 form.fields[self._pk_field.name] = IntegerField(required=False, widget=HiddenInput)
428 super(BaseModelFormSet, self).add_fields(form, index)
430 def modelformset_factory(model, form=ModelForm, formfield_callback=lambda f: f.formfield(),
431 formset=BaseModelFormSet,
432 extra=1, can_delete=False, can_order=False,
433 max_num=0, fields=None, exclude=None):
435 Returns a FormSet class for the given Django model class.
437 form = modelform_factory(model, form=form, fields=fields, exclude=exclude,
438 formfield_callback=formfield_callback)
439 FormSet = formset_factory(form, formset, extra=extra, max_num=max_num,
440 can_order=can_order, can_delete=can_delete)
441 FormSet.model = model
442 return FormSet
445 # InlineFormSets #############################################################
447 class BaseInlineFormSet(BaseModelFormSet):
448 """A formset for child objects related to a parent."""
449 def __init__(self, data=None, files=None, instance=None,
450 save_as_new=False, prefix=None):
451 from django.db.models.fields.related import RelatedObject
452 self.instance = instance
453 self.save_as_new = save_as_new
454 # is there a better way to get the object descriptor?
455 self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
456 super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix or self.rel_name)
458 def _construct_forms(self):
459 if self.save_as_new:
460 self._total_form_count = self._initial_form_count
461 self._initial_form_count = 0
462 super(BaseInlineFormSet, self)._construct_forms()
464 def _construct_form(self, i, **kwargs):
465 form = super(BaseInlineFormSet, self)._construct_form(i, **kwargs)
466 if self.save_as_new:
467 # Remove the primary key from the form's data, we are only
468 # creating new instances
469 form.data[form.add_prefix(self._pk_field.name)] = None
470 return form
472 def get_queryset(self):
474 Returns this FormSet's queryset, but restricted to children of
475 self.instance
477 kwargs = {self.fk.name: self.instance}
478 return self.model._default_manager.filter(**kwargs)
480 def save_new(self, form, commit=True):
481 kwargs = {self.fk.get_attname(): self.instance.pk}
482 new_obj = self.model(**kwargs)
483 return save_instance(form, new_obj, exclude=[self._pk_field.name], commit=commit)
485 def add_fields(self, form, index):
486 super(BaseInlineFormSet, self).add_fields(form, index)
487 if self._pk_field == self.fk:
488 form.fields[self._pk_field.name] = IntegerField(required=False, widget=HiddenInput)
490 def _get_foreign_key(parent_model, model, fk_name=None):
492 Finds and returns the ForeignKey from model to parent if there is one.
493 If fk_name is provided, assume it is the name of the ForeignKey field.
495 # avoid circular import
496 from django.db.models import ForeignKey
497 opts = model._meta
498 if fk_name:
499 fks_to_parent = [f for f in opts.fields if f.name == fk_name]
500 if len(fks_to_parent) == 1:
501 fk = fks_to_parent[0]
502 if not isinstance(fk, ForeignKey) or \
503 (fk.rel.to != parent_model and
504 fk.rel.to not in parent_model._meta.get_parent_list()):
505 raise Exception("fk_name '%s' is not a ForeignKey to %s" % (fk_name, parent_model))
506 elif len(fks_to_parent) == 0:
507 raise Exception("%s has no field named '%s'" % (model, fk_name))
508 else:
509 # Try to discover what the ForeignKey from model to parent_model is
510 fks_to_parent = [
511 f for f in opts.fields
512 if isinstance(f, ForeignKey)
513 and (f.rel.to == parent_model
514 or f.rel.to in parent_model._meta.get_parent_list())
516 if len(fks_to_parent) == 1:
517 fk = fks_to_parent[0]
518 elif len(fks_to_parent) == 0:
519 raise Exception("%s has no ForeignKey to %s" % (model, parent_model))
520 else:
521 raise Exception("%s has more than 1 ForeignKey to %s" % (model, parent_model))
522 return fk
525 def inlineformset_factory(parent_model, model, form=ModelForm,
526 formset=BaseInlineFormSet, fk_name=None,
527 fields=None, exclude=None,
528 extra=3, can_order=False, can_delete=True, max_num=0,
529 formfield_callback=lambda f: f.formfield()):
531 Returns an ``InlineFormSet`` for the given kwargs.
533 You must provide ``fk_name`` if ``model`` has more than one ``ForeignKey``
534 to ``parent_model``.
536 fk = _get_foreign_key(parent_model, model, fk_name=fk_name)
537 # enforce a max_num=1 when the foreign key to the parent model is unique.
538 if fk.unique:
539 max_num = 1
540 if exclude is not None:
541 exclude = list(exclude)
542 exclude.append(fk.name)
543 else:
544 exclude = [fk.name]
545 kwargs = {
546 'form': form,
547 'formfield_callback': formfield_callback,
548 'formset': formset,
549 'extra': extra,
550 'can_delete': can_delete,
551 'can_order': can_order,
552 'fields': fields,
553 'exclude': exclude,
554 'max_num': max_num,
556 FormSet = modelformset_factory(model, **kwargs)
557 FormSet.fk = fk
558 return FormSet
561 # Fields #####################################################################
563 class ModelChoiceIterator(object):
564 def __init__(self, field):
565 self.field = field
566 self.queryset = field.queryset
568 def __iter__(self):
569 if self.field.empty_label is not None:
570 yield (u"", self.field.empty_label)
571 if self.field.cache_choices:
572 if self.field.choice_cache is None:
573 self.field.choice_cache = [
574 self.choice(obj) for obj in self.queryset.all()
576 for choice in self.field.choice_cache:
577 yield choice
578 else:
579 for obj in self.queryset.all():
580 yield self.choice(obj)
582 def choice(self, obj):
583 if self.field.to_field_name:
584 # FIXME: The try..except shouldn't be necessary here. But this is
585 # going in just before 1.0, so I want to be careful. Will check it
586 # out later.
587 try:
588 key = getattr(obj, self.field.to_field_name).pk
589 except AttributeError:
590 key = getattr(obj, self.field.to_field_name)
591 else:
592 key = obj.pk
593 return (key, self.field.label_from_instance(obj))
596 class ModelChoiceField(ChoiceField):
597 """A ChoiceField whose choices are a model QuerySet."""
598 # This class is a subclass of ChoiceField for purity, but it doesn't
599 # actually use any of ChoiceField's implementation.
600 default_error_messages = {
601 'invalid_choice': _(u'Select a valid choice. That choice is not one of'
602 u' the available choices.'),
605 def __init__(self, queryset, empty_label=u"---------", cache_choices=False,
606 required=True, widget=None, label=None, initial=None,
607 help_text=None, to_field_name=None, *args, **kwargs):
608 self.empty_label = empty_label
609 self.cache_choices = cache_choices
611 # Call Field instead of ChoiceField __init__() because we don't need
612 # ChoiceField.__init__().
613 Field.__init__(self, required, widget, label, initial, help_text,
614 *args, **kwargs)
615 self.queryset = queryset
616 self.choice_cache = None
617 self.to_field_name = to_field_name
619 def _get_queryset(self):
620 return self._queryset
622 def _set_queryset(self, queryset):
623 self._queryset = queryset
624 self.widget.choices = self.choices
626 queryset = property(_get_queryset, _set_queryset)
628 # this method will be used to create object labels by the QuerySetIterator.
629 # Override it to customize the label.
630 def label_from_instance(self, obj):
632 This method is used to convert objects into strings; it's used to
633 generate the labels for the choices presented by this object. Subclasses
634 can override this method to customize the display of the choices.
636 return smart_unicode(obj)
638 def _get_choices(self):
639 # If self._choices is set, then somebody must have manually set
640 # the property self.choices. In this case, just return self._choices.
641 if hasattr(self, '_choices'):
642 return self._choices
644 # Otherwise, execute the QuerySet in self.queryset to determine the
645 # choices dynamically. Return a fresh QuerySetIterator that has not been
646 # consumed. Note that we're instantiating a new QuerySetIterator *each*
647 # time _get_choices() is called (and, thus, each time self.choices is
648 # accessed) so that we can ensure the QuerySet has not been consumed. This
649 # construct might look complicated but it allows for lazy evaluation of
650 # the queryset.
651 return ModelChoiceIterator(self)
653 choices = property(_get_choices, ChoiceField._set_choices)
655 def clean(self, value):
656 Field.clean(self, value)
657 if value in EMPTY_VALUES:
658 return None
659 try:
660 key = self.to_field_name or 'pk'
661 value = self.queryset.get(**{key: value})
662 except self.queryset.model.DoesNotExist:
663 raise ValidationError(self.error_messages['invalid_choice'])
664 return value
666 class ModelMultipleChoiceField(ModelChoiceField):
667 """A MultipleChoiceField whose choices are a model QuerySet."""
668 widget = SelectMultiple
669 hidden_widget = MultipleHiddenInput
670 default_error_messages = {
671 'list': _(u'Enter a list of values.'),
672 'invalid_choice': _(u'Select a valid choice. %s is not one of the'
673 u' available choices.'),
676 def __init__(self, queryset, cache_choices=False, required=True,
677 widget=None, label=None, initial=None,
678 help_text=None, *args, **kwargs):
679 super(ModelMultipleChoiceField, self).__init__(queryset, None,
680 cache_choices, required, widget, label, initial, help_text,
681 *args, **kwargs)
683 def clean(self, value):
684 if self.required and not value:
685 raise ValidationError(self.error_messages['required'])
686 elif not self.required and not value:
687 return []
688 if not isinstance(value, (list, tuple)):
689 raise ValidationError(self.error_messages['list'])
690 final_values = []
691 for val in value:
692 try:
693 obj = self.queryset.get(pk=val)
694 except self.queryset.model.DoesNotExist:
695 raise ValidationError(self.error_messages['invalid_choice'] % val)
696 else:
697 final_values.append(obj)
698 return final_values