2015-03-26 3 views
1

Я работаю над некоторыми формами Django, для которых база кода наследуется от кого-то другого, что хорошо, но добавляет к путанице.Django: Несколько форм в форме

Я пытаюсь добавить второй набор форм в форму. Когда добавляется второй набор форм, оба набора форм появляются на странице, но, по-видимому, не содержат никаких форм на бэкэнд. Вот пример моего кода (я добавил больше, чем, вероятно, рекомендуется, но я не хочу пропустить что-то важное):

view.py:

class Thing(StaffRequiredMixin, DetailView): 
model = models.Thing 

def post(self, request, *args, **kwargs): 

    ... 

    context = self.get_context_data(**kwargs) 

    dispatch = { 
     "thing_form": self.handle_thing_form, 
     ... 
    } 

    return dispatch[self.request.POST.get("form_name")](context) 

... 

def get_context_data(self, *args, **kwargs): 

    context = super(Thing, self).get_context_data(*args, **kwargs) 
    thing = self.model.objects.get(pk=self.kwargs["pk"]) 
    context["thing"] = thing 

    to_handle = self.request.POST.get("form_name") 

    if to_handle == "thing_form": 
     context["thing_form"] = forms.Thing(
        self.request.POST, 
        instance=thing) 

     context["formset1"] = forms.FormSet1(
        self.request.POST, 
        queryset=models.Model1.objects.filter(thing=self.object), 
        prefix="thing1") 

     context["formset2"] = forms.FormSet2(
        self.request.POST, 
        queryset=models.Model2.objects.filter(thing=self.object), 
        prefix="thing2") 
    else: 
     context["thing_form"] = forms.Thing(
        instance=thing, 
        user=self.request.user) 

     context["formset1"] = forms.FormSet1(
        queryset=models.Model1.objects.filter(thing=self.object), 
        prefix="stuff1") 

     context["formset2"] = forms.FormSet2(
        queryset=models.Model2.objects.filter(thing=self.object), 
        prefix="stuff2") 

    # Other to_handle stuff 
    ... 

    return context 

def handle_thing_form(self, context): 

    form = context['thing_form'] 
    formset1 = context['formset1'] 
    formset2 = context['formset2'] 

    if form.is_valid() and formset1.is_valid() and formset2.is_valid(): 

     # Do some form logic 
     ... 

     form.save() 

     # Formset stuff: 
     # here, the formsets contain no forms 
     changed_1 = [f for f in formset1 if f.has_changed()] 
     changed_2 = [f for f in formset2 if f.has_changed()] 

     for a_form in changed_1: 

      #Do some formset logic 
      ... 

      a_form.save() 

     for a_form in changed_2: 
      #similar to 1 

     return HttpResponseRedirect(self.get_next_url()) 

    return self.render_to_response(context) 

forms.py:

class Form1(ModelForm): 

    class Meta: 
     model = models.Model1 
     fields = ("field1", "field2", ...) 

    def __init__(self, *args, **kwargs): 

     super(Form1, self).__init__(*args, **kwargs) 

     # Some readonly widget stuff etc 
     ... 


class Form2(ModelForm): 

    #Same idea as Form1 
    ... 


FormSet1 = modelformset_factory(models.Model1, form=Form1, extra=0) 
FormSet2 = modelformset_factory(models.Model2, form=Form2, extra=0) 

шаблона:

<form id="thing-form" method="post"> 
    <input type="hidden" name="form_name" value="thing_form" /> 

    {% for field in thing_form.visible_fields %} 

     {{ field }} 
     ... 

    {% endfor %} 


    <a id="add-form1">Add</a> 

    {{formset1.management_form}} 
    <div id="formset1-div"> 

     {% for form in formset1.forms %} 

      {{form.id}} 
      {% for field in form.visible_fields %} 

       <div class="controls"> 
        {{field}} 
       </div> 

      {% endfor %} 
     {% endfor %} 
    </div> 

    <div id="empty-form1> 

     {% for field in formset1.empty_form.visible_fields %} 
      <div class="controls"> 
       {{field}} 
      </div> 
     {% endfor %} 
    </div> 

    {{formset2.management_form}} 
    <div id="formset2-div"> 

     {# same idea as above #} 
     ... 

    </div> 

    <button type="submit">Update</button> 
</form> 

JavaScript:

$(document).ready(function(){ 

    $('#add-form1').click(function() { 
     $('#formset1-div').prepend($('#empty_form1').html().replace(/__prefix__/g, 'thing1')); 
     $('#id_form-TOTAL_FORMS').val(parseInt('thing1') + 1); 
    }); 

    if ($("#formset1-div input").length === 0){ 
     $("#add-form1").trigger("click"); 
    } 

    // Similar button stuff for formset2 
    ... 

}) 

В любом случае, я добавил много здесь, но я сделал это, потому что я не уверен, где я ошибся, или даже если то, что я пытаюсь сделать, возможно.

ответ

1

WOW Я настолько тупой. Javascript часть должна быть что-то вроде:

$(document).ready(function(){ 

    $('#add-form1').click(function() { 
     var thing1_index = $('#id_thing1-TOTAL_FORMS').val(); 
     $('#formset1-div').prepend($('#empty_form1').html().replace(/__prefix__/g, thing1_index)); 
     $('#id_thing1-TOTAL_FORMS').val(parseInt(thing1_index) + 1); 
    }); 

    if ($("#formset1-div input").length === 0){ 
     $("#add-form1").trigger("click"); 
    } 

    // Similar button stuff for formset2 
    ... 

}) 

Не знаю, как я пропустил очевидное parseInt('thing1') не имеет никакого смысла.

Anyways, сейчас он работает. Может быть, кто-то, глядя на несколько форм, найдет что-то полезное здесь ¯\_(ツ)_/¯

+1

Нет, вы не глупы, тем не менее, шаблоны Django не поддаются сложным веб-интерфейсам. Как и вы, я обнаружил, что шаблоны вскоре стали слишком хрупкими для поддержания. Несколько вложенных форм в конечном итоге привели меня в AngularJS, используя Django и Django REST Framework в качестве бэкэнд. Я нашел, что комбо работает неплохо. Просто мой 2 ¢, рад, что вы это поняли. – Fiver

Смежные вопросы