django-angular очень круто. В частности, мне нравится, как он автоматизирует ошибки рендеринга. У меня есть куча форм, где это работает очень хорошо. Я пытаюсь сделать то же самое с wetetets и столкнуться с проблемами.Использование форм в django-angular
Во-первых, возникла проблема с именами полей, которые не отображаются в базовые угловые модели. Я использую вложенную модель, как это:
var parent = {
field1 : 'a',
field2: 'b',
child_model: [
{ childfield1: 'c',
childfield2: 'd'
},
{ childfield1: 'e',
childfield2: 'f'
}
]
}
Для того, чтобы получить эту структуру для сопоставления полой формы, я использую следующий код:
class MyFormSet(BaseInlineFormSet):
def _construct_form(self, i, **kwargs):
"""
Instantiates and returns the i-th form instance in a formset.
"""
defaults = {
'auto_id': self.auto_id,
'prefix': self.add_prefix(i),
'error_class': self.error_class,
# THESE NEXT 3 LINES ARE THE DIFFERENT BIT...
'formset_class': self.__class__,
'scope_prefix': "%s[%d]" % (self.scope_prefix, i),
'form_name': "%s-%s" % (self.formset_name, i),
}
if self.is_bound:
defaults['data'] = self.data
defaults['files'] = self.files
if self.initial and 'initial' not in kwargs:
try:
defaults['initial'] = self.initial[i]
except IndexError:
pass
# Allow extra forms to be empty, unless they're part of
# the minimum forms.
if i >= self.initial_form_count() and i >= self.min_num:
defaults['empty_permitted'] = True
defaults.update(kwargs)
form = self.form(**defaults)
self.add_fields(form, i)
return form
class MyChildForm(Bootstrap3ModelForm, NgModelFormMixin, NgFormValidationMixin):
class Meta:
model = MyChildModel
def __init__(self, *args, **kwargs):
formset_class = kwargs.pop("formset_class", None)
super(MyChildForm, self).__init__(*args, **kwargs)
self.formset_class = formset_class
def get_widget_attrs(self, bound_field):
"""
just like the base class fn
except it sets "ng-model" using "get_qualified_model_field_name"
"""
attrs = super(NgModelFormMixin, self).get_widget_attrs(bound_field)
identifier = self.add_prefix(bound_field.name)
ng = {
'name': bound_field.name,
'identifier': identifier,
'model': self.get_qualified_model_field_name(bound_field.name)
}
if hasattr(self, 'Meta') and bound_field.name in getattr(self.Meta, 'ng_models', []):
attrs['ng-model'] = ng['model']
for key, fmtstr in self.ng_directives.items():
attrs[key] = fmtstr % ng
return attrs
def is_formset(self):
"""
tells whether or not the form is a member of a formset
"""
return self.formset_class is not None
def get_qualified_form_field_name(self, field_name):
"""
gets a field name suitable for ng use when binding to form
"""
if self.is_formset():
identifier = field_name
else:
identifier = self.add_prefix(field_name)
return format_html("{0}['{1}']", self.form_name, identifier)
def get_qualified_model_field_name(self, field_name):
"""
gets a field name suitable for ng use when binding to model
"""
if self.is_formset():
identifier = field_name
else:
identifier = self.add_prefix(field_name)
return format_html("{0}['{1}']", self.scope_prefix, identifier)
def MyChildModelFormSetFactory(*args, **kwargs):
instance = kwargs.pop("instance", None)
initial = kwargs.pop("initial", [])
queryset = kwargs.pop("queryset", MyChildModel.objects.none())
prefix = kwargs.pop("prefix", None)
scope_prefix = kwargs.pop("scope_prefix", None)
formset_name = kwargs.pop("formset_name", None)
kwargs.update({
"can_delete": False,
"extra": kwargs.pop("extra", 0),
"formset": MyFormSet,
"form": MyChildForm,
})
formset = inlineformset_factory(MyParentModel, MyChildModel, *args, **kwargs)
formset.scope_prefix = scope_prefix
formset.formset_name = formset_name
return formset(instance=instance, initial=initial, queryset=queryset)
Изменение get_widget_attrs
правильно делает такую область, как это:
<input class="form-control ng-pristine ng-untouched ng-valid ng-valid-parse ng-valid-required ng-valid-maxlength" id="id_my_formset_name-0.field_name" name="my_formset_name-0.field_name" ng-model="parent.child_model[0]['field_name']">
Но когда я пытаюсь сделать {{field.errors}}
я просто получить кучу мусора. Вместо чувствительных элементов ж/всех ожидаемых Джанго-угловых классов («djng-полевые ошибки» и т.д.), я получаю необработанный текст вроде этого:
(u'my_formset_name-0.my_scope_prefix-0.my_field_name', u'djng-form-control-feedback djng-field-errors', u'$dirty', u'$error.required', u'invalid', u'This field is required.')
Любые идеи?
обновление:
Для чего это стоит, если я печатаю, что .get_field_errors
возвращается с поля из формы «автономные» я получаю:
<ul class="djng-form-control-feedback djng-field-errors" ng-show="my_form_name['field1'].$dirty" ng-cloak>
<li ng-show="my_form_name['field1'].$error.required" class="invalid">This field is required.</li>
</ul>
И если я распечатать то, что .get_field_errors
возвращается с поля из формы, которая является частью formset я получаю:
<ul class="errorlist">
<li>("my_formset_name-0['childfield1']", u'djng-form-control-feedback djng-field-errors', '$dirty', u'$error.required', 'invalid', u'This field is required.')</li>
</ul>
В дополнение к HTML не будет экранирован, обратите внимание, что родительский элемент имеет неправильный класс.