简体   繁体   English

Django form.is_valid()清除所需的值

[英]Django form.is_valid() cleans needed values

I am practicing Django, and I have been stuck on this for a while now. 我正在练习Django,现在已经坚持了一段时间。 I am trying to write a basic survey app. 我正在尝试编写一个基本的调查应用程序。 My issue is that when I submit my form, I can see that request.POST contains the data I need, form.data also contains it, but after I run form.is_valid() , I am left with only the keys in the dict, no values. 我的问题是,当我提交表单时,我可以看到该request.POST form.data包含了我需要的数据, form.data也包含了它,但是在运行form.is_valid() ,我只剩下字典中的键,没有值。

class SurveyForm(forms.Form):
    def __init__(self, *args, **kwargs):
        questions = kwargs.pop('questions')
        super(SurveyForm, self).__init__(*args, **kwargs)

        for q in questions:
            choices = []
            for answer in q.choice_set.all():
                choices.append((answer.pk, answer.choice_text))

            self.fields[q.id] = forms.ChoiceField(label=q.question_text, required=False,
                                  choices=choices, widget=forms.RadioSelect)

    def answers(self):
        for q, a in self.cleaned_data.items():
            yield a

If I remove required=False , I keep getting This field is required although, I believe it's due to the validation, because it looks like the page refreshes when I hit submit, while if I actually leave the choices blank, it doesn't refresh and instead a small popup appears above the label. 如果我删除了required=False ,那么我一直保持This field is required尽管我认为这是由于验证所致,因为当我单击“提交”时,页面看起来像在刷新,而如果我将选项保留为空白,则不会刷新而是在标签上方显示了一个小弹出窗口。

Here is the view that uses it. 这是使用它的视图。

def step(request, survey_id, attempt_id, surveypage_nr):
    survey = get_object_or_404(Survey, pk=survey_id)
    attempt = get_object_or_404(Attempt, pk=attempt_id)
    pages = survey.surveypage_set.all().order_by('page_nr')
    page = pages.filter(page_nr=surveypage_nr).first();
    questions = page.question_set.all()

    form = SurveyForm(request.POST or None, questions=questions)

    if form.is_valid():
        for a in form.answers():
            answer = get_object_or_404(Choice, pk=a)
            attempt.score = attempt.score + answer.score
        attempt.save()
        return HttpResponseRedirect(reverse('results', args=(survey.id, attempt.id,)))

    else:
        context = {'page': page, 'form': form}
        return render(request, 'survey/surveypage.html', context)

I tried checking the contents of the form after the is_valid() call: 我尝试在is_valid()调用之后检查表单的内容:

request.POST = {'3': '2', '4': '3', 'csrfmiddlewaretoken': 'f..m1'}
form.data = {'3': '2', '4': '3', 'csrfmiddlewaretoken': 'f..m1'}
form.cleaned_data = {3: '', 4: ''}.    # Why are you cleaning my values, Django?


form.fields = OrderedDict([(3, <django.forms.fields.ChoiceField object at 0x106c2d5f8>),
         (4, <django.forms.fields.ChoiceField object at 0x1055ebba8>)])

As you can see, request.POST and form.data contain exactly what I need, but after validation, form.cleaned_data doesn't have values for the keys. 如您所见, request.POSTform.data完全包含我所需要的内容,但是在验证之后, form.cleaned_data没有键的值。 Why is this happening? 为什么会这样呢? Help pls. 帮助请。

form.cleaned_data的键是string,而form.data是int。

As the other answer pointed out, the key needs to be a string. 正如另一个答案指出的那样,密钥必须是字符串。 Data in a POST is always a string, but your keys are currently int. POST中的数据始终是字符串,但是您的密钥当前为int。 So when Django goes to validate the data for field '3' it finds nothing, so shows it as empty; 因此,当Django验证字段'3'的数据时,它什么也没找到,因此将其显示为空。 meanwhile it doesn't have a field called 3 so throws away that key/value. 同时,它没有名为3的字段,因此会丢弃该键/值。

You should set your field IDs to strings: 您应该将字段ID设置为字符串:

self.fields[str(q.id)] = ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM