使用基于类的视图提交表单集数据

时间:2019-08-16 05:45:52

标签: python django

我正在使用django创建一个包含孩子信息的表单集。我为此使用createview(CBV)。该窗体显示正确,它具有添加子项和删除所有正常工作的子项的功能。但是,当我单击“提交”时,将调用form_invalid而不是form_valid。为了知道这个问题,我打印了form.errors,发现了以下错误

<ul class="errorlist"><li>deal_id<ul class="errorlist"><li>This field is required.</li></ul></li><li>child_name<ul class="errorlist"><li>This field is required.</li></ul></li><li>son_or_daugher<ul class="errorlist"><li>This field is required.</li></ul></li><li>child_age<ul class="errorlist"><li>This field is required.</li></ul></li><li>child_education<ul class="errorlist"><li>This field is required.</li></ul></li><li>child_occupation<ul class="errorlist"><li>This field is required.</li></ul></li></ul>

下面是我的代码

模板:-

{% extends "forms_app/base.html" %}
{% load static %}

{% block title %}{% endblock %}
{% block content %}
    <h2>Profile</h2>
    <hr>
    <div class="col-md-4">
        <form action="" method="post">{% csrf_token %}
            <table class="table">
                {{ childrens.management_form }}

                {% for form in childrens.forms %}
                    {% if forloop.first %}
                        <thead>
                        <tr>
                            {% for field in form.visible_fields %}
                                <th>{{ field.label|capfirst }}</th>
                            {% endfor %}
                        </tr>
                        </thead>
                    {% endif %}
                    <tr class="{% cycle row1 row2 %} formset_row">
                        {% for field in form.visible_fields %}
                            <td>
                                {# Include the hidden fields in the form #}
                                {% if forloop.first %}
                                    {% for hidden in form.hidden_fields %}
                                        {{ hidden }}
                                    {% endfor %}
                                {% endif %}
                                {{ field.errors.as_ul }}
                                {{ field }}
                            </td>
                        {% endfor %}
                    </tr>
                {% endfor %}
            </table>
            <input type="submit" value="Submit"/> <a href="">back to the list</a>
        </form>
    </div>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="{% static 'forms_app/jquery.formset.js' %}"></script>
    <script type="text/javascript">
        $('.formset_row').formset({
            addText: 'Add Children',
            deleteText: 'Remove',
            prefix: 'familymember_set'
        });
    </script>
{% endblock %}

查看代码

class ChildrenView(CreateView):
    template_name = 'forms_app/children_form.html'
    form_class = ChildrenForm
    success_url = reverse_lazy('forms_app:deal-entering')

    # fields = ['name','class']

    def get_context_data(self, **kwargs):
        data = super(ChildrenView, self).get_context_data(**kwargs)
        if self.request.POST:
            data['childrens'] = ChildrenFormSet(self.request.POST)
        else:
            print('child form initial data')
            initial_list = []
            try:
                print('its going on')
                for i in range(self.request.session['children_count']   ):
                    print('still going on')
                    for field in self.fields:
                        initial_list.append(self.request.session[i + field])
                        data['childrens'] = ChildrenFormSet(initial = initial_list)
            except:
                data['childrens'] = ChildrenFormSet()
            # data['childrens'].extra = self.request.session['children_count']
        return data


    def form_valid(self, form):
        if form.is_valid():
            count = 0
            for f in form:
                for field in ['deal_id','child_name','son_or_daugher','child_age','child_education','child_occupation']:
                    self.request.session[count + field] = f.cleaned_data[field]
                count += 1

            self.request.session['children_count'] = count

            for i in range(count):
                for field in ['deal_id','child_name','son_or_daugher','child_age','child_education','child_occupation']:
                    print(self.request.session[i + field])


            for field in self.fields:
                self.request.session[field] = form.cleaned_data[field]

            self.request.session['valid_children'] = True

        return super(ChildrenView, self).form_valid(form)


    def form_invalid(self,form):

        if form.is_valid():
            pass
        print(form.errors)
        print('form invalid')
        return super(ChildrenView, self).form_invalid(form)

表格代码

class ChildrenForm(forms.ModelForm):
    class Meta:
        model = Children
        fields = '__all__'


    def clean(self):
        print(self.cleaned_data)

ChildrenFormSet = modelformset_factory(Children,fields = '__all__',extra=1)

我已经阅读了StackOverflow上的几篇文章。我浏览了django文档,但仍然无法解决问题。请帮我。

下面是我的表单的屏幕截图 enter image description here

如果您对理解有任何疑问,请发表评论,我会尽快答复。

3 个答案:

答案 0 :(得分:1)

问题可能出在此行:

form_class = ChildrenForm

尝试删除该行或将其更改为:

form_class = ChildrenFormSet

我认为您的form_valid正在检查“ ChildrenForm”表单。

答案 1 :(得分:1)

我认为您需要完全忽略form_valid,因为您没有有效的ChildrenForm,因此请改用post方法

尝试这样的事情:

def post(self, *args, **kwargs):
    formset = ChildrenFormSet(self.request.POST)
    if formset.is_valid():
       do stuff
    else :
       return self.form.is_invlaid()
    return redirect to your success url

答案 2 :(得分:1)

您的模板呈现ChildrenFormSet而不是ChildrenForm

因此,用户在ChildrenView验证ChildrenForm时不可避免地使用空白集。

@HenryM提供了一种逻辑解决方案(我尚未测试过),但是它取消了使用CreateView的含义。

我将使用FormView来直接操作Formset:

forms.py:

class ChildrenView(FormView):
    template_name = 'forms_app/children_form.html'
    form_class = ChildrenFormSet
    success_url = reverse_lazy('forms_app:deal-entering')

    def form_valid(self, form):
        """
        If the formset is valid, create the objects in the database
        """
        instances = []
        for sub_form in form:
            obj = Children(**sub_form.cleaned_data)
            instances.append(obj)
        Children.objects.bulk_create(instances)
        return super().form_valid(form)

    def get_form_kwargs(self):
        """
        Here you define the queryset that gathers the forms presented to the user.
        We return none() in order to have always an empty formset and simplify the code.
        """
        kwargs = super().get_form_kwargs()
        kwargs["queryset"] = Children.objects.none()
        return kwargs

children_form.html:

{% extends "forms_app/base.html" %}
{% load static %}

{% block title %}{% endblock %}
{% block content %}
    <h2>Profile</h2>
    <hr>
    <div class="col-md-4">
        <form action="" method="post">{% csrf_token %}
          {{ form.as_table }}
          <input type="submit" value="Submit"/> <a href="">back to the list</a>
        </form>
    </div>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="{% static 'forms_app/jquery.formset.js' %}"></script>
    <script type="text/javascript">
        $('.formset_row').formset({
            addText: 'Add Children',
            deleteText: 'Remove',
            prefix: 'familymember_set'
        });
    </script>
{% endblock %}