2015-10-06 6 views
0

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>(&quot;my_formset_name-0[&#39;childfield1&#39;]&quot;, u&#39;djng-form-control-feedback djng-field-errors&#39;, &#39;$dirty&#39;, u&#39;$error.required&#39;, &#39;invalid&#39;, u&#39;This field is required.&#39;)</li> 
</ul> 

В дополнение к HTML не будет экранирован, обратите внимание, что родительский элемент имеет неправильный класс.

ответ

0

Проблема была простой. django-угловые формы используют пользовательский error_class. Но _construct_form fn переопределяет это. Мне просто нужно было указать тот же класс ошибок в FormSet:

class MyFormSet(BaseInlineFormSet): 

    def __init__(self, *args, **kwargs): 
     kwargs.update({ 
      # makes sure that child forms render errors correctly... 
      "error_class": TupleErrorList, 
     }) 
     super(MyFormSet, self).__init__(*args, **kwargs) 
Смежные вопросы