1

因此,每次尝试提交表单集时,我都会收到 KeyError。我之前在这里
问过一个类似的问题,解决方案似乎工作了一段时间,但现在我得到了上面提到的 KeyError。 下面的代码和跟踪:

形式:

class CodingForm(forms.Form):
    NATIONAL = 0
    REGIONAL = 1
    LOCAL = 2
    NA = 99
    SCOPE_CHOICES = (
        (NA, 'No Report'),
        (NATIONAL, 'National'),
        (REGIONAL, 'Regional'),
        (LOCAL, 'Local'),
    )

    NO_VIO = 0
    PROP_DMG = 1
    INJ = 2
    KILL = 3

    PART_VIO = (
        (NA, 'No Report'),
        (NO_VIO, 'No Violence'),
        (PROP_DMG, 'Property Damage'),
        (INJ, 'People Injured'),
        (KILL, 'People Killed'),
    )

    NO_PRES = 0
    PRES = 1
    INT = 2
    LETHAL_INT = 3

    SEC_ENG = (
        (NA, 'No Report'),
        (NO_PRES, 'No Presence'),
        (PRES, 'Presence'),
        (INT, 'Intervention'),
        (LETHAL_INT, 'Lethal Intervention'),
    )

    event_date = forms.DateField(required=False)
    location = GeonamesChoiceField(queryset=Geonames.objects.all(), required=False)
    actors = forms.CharField(max_length=100, required=False)
    num_participants = forms.CharField(max_length=200, required=False)  
    issue = forms.CharField(max_length=200, required=False)
    side = forms.NullBooleanField('Side')
    scope = forms.TypedChoiceField(choices=SCOPE_CHOICES, coerce=int, empty_value=None)
    part_violence = forms.TypedChoiceField(choices=PART_VIO, coerce=int, empty_value=None)
    sec_engagement = forms.TypedChoiceField(choices=SEC_ENG, coerce=int)
    relevance = forms.NullBooleanField('relevance')


    def clean(self):
            cleaned_data = self.cleaned_data
            event_date = cleaned_data.get("event_date")
            location = cleaned_data.get("location")

            if event_date and location:
                cleaned_data['relevance'] = True
                print cleaned_data["relevance"]
            else:
                cleaned_data['relevance'] = False

            return cleaned_data

看法:

def assignment(request, pk):
"""View for each assignment"""
if request.user.is_authenticated():

    #### Get correct articles
    assignment = get_object_or_404(Assignment, pk=pk)
    country = assignment.country.cowcode
    start_date = assignment.start_date
    end_date = assignment.end_date
    articles = Article.objects.filter(cowcode=country).filter(pubdate__range=(start_date,end_date))

    #### Pagination ####
    paginator = Paginator(articles, 1)
    page = request.GET.get('page')
    try:
        articles = paginator.page(page)
    except PageNotAnInteger:
        articles = paginator.page(1)
    except EmptyPage:
        articles = paginator(page(paginator.num_pages))

    # Check if on first page and enable redirect
    if page is None:
        current_page = 1
    else:
        current_page = page
    redirect_to = "?page=%s" % current_page

    CodingFormSet = formset_factory(CodingForm, extra=0)
    formset = CodingFormSet(request.POST or None, prefix="coding_form")

    location_queryset = Geonames.objects.filter(cowcode=country).order_by('name')
    for form in formset.forms:
           form.fields['location'].queryset = location_queryset

    ##### Check if coder wants to go to next page or stay
    if "coding_form_next" in request.POST:
        process_form(formset, request, current_page, paginator)
        current_page = int(current_page) + 1
        redirect_to = "?page=%s" % current_page
        return HttpResponseRedirect(redirect_to)
    elif "coding_form_save" in request.POST:
        process_form(formset, request, current_page, paginator)
        redirect_to = "?page=%s" % current_page
        return HttpResponseRedirect(redirect_to)

else:
    print ERROR
return render(request, 'coding/assignment.html', 
{'articles':articles,'assignment':assignment,'formset':formset})

def process_form(formset, request, current_page, paginator):
if formset.is_valid():
    for form in formset.forms:
        form = form.cleaned_data

        if form['relevance'] == False:
            pass
        elif form['relevance'] == True:


            event_form = EventRecordForm()

            event = event_form.save(commit=False)
            event.article = paginator.page(current_page).object_list[0]
            event.coder = request.user
            event.last_updated = datetime.datetime.today()
            event.event_date = form["event_date"]
            event.location = form["location"]
            event.actors = form["actors"]
            event.num_participants = form["num_participants"]
            event.issue = form["issue"]
            event.side = form["side"]
            event.scope = form["scope"]
            event.part_violence = form["part_violence"]
            event.sec_engagement = form["sec_engagement"]
            event.save()

    ##### Add info on who worked on the article when
    history_form = ArticleHistoryForm()
    article_history = history_form.save(commit=False)
    article_history.article = paginator.page(current_page).object_list[0]
    article_history.coder = request.user
    article_history.last_updated = datetime.datetime.now()
    article_history.save()

模板:

<div id="coding">
<div id="coding-inner">
    {% with formset.empty_form as form %}
    <div id="empty_form" style="display:none">
        <table border="0" cellspacing="5" cellpadding="5">
            <tbody>
            <tr>
                <td>{{ form.event_date.label_tag}}</td>
                <td>{{ form.event_date}}</td>
            </tr>
            <tr>
                <td>{{ form.location.label_tag }}</td>
                <td><div class="location_wrapper">{{ form.location }}</div></td>
            </tr>
            <tr>
                <td>{{ form.actors.label_tag }}</td>
                <td>{{ form.actors }}</td>
            </tr>
            <tr>
                <td>{{ form.num_participants.label_tag }}</td>
                <td>{{ form.num_participants }}</td>
            </tr>
            <tr>
                <td>{{ form.issue.label_tag }}</td>
                <td>{{ form.issue }}</td>
            </tr>
            <tr>
                <td>{{ form.side.label_tag }}</td>
                <td>{{ form.side }}</td>
            </tr>
            <tr>
                <td>{{ form.scope.label_tag }}</td>
                <td>{{ form.scope }}</td>
            </tr>
            <tr>
                <td>{{ form.part_violence.label_tag}}</td>
                <td>{{ form.part_violence}}</td>
            </tr>
            <tr>
                <td>{{ form.sec_engagement.label_tag }}</td>
                <td>{{ form.sec_engagement }}</td>
            </tr>
            <tr>
                <td>{{ form.relevance.label_tag }}<td>
                <td>{{ form.relevance }}<td>
            </tr>
        </tbody>
        </table>
    </div>
    {% endwith %}
    <form action="" method="post" accept-charset="utf-8" id="form"> 
        {% csrf_token %}
        <div class="form-container"></div>
        {{ formset.management_form }}
        <div id="form-nav">

            <div id="save-stay">
                <input type="submit" name="coding_form_save" value="Save">
            </div>
            <div id="save-next">
                <input type="submit" name="coding_form_next" value="Save &#38; Next">
            </div>

        </div>
    </form>

</div>

和跟踪:

Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/coding/assignment/1/?page=1

Django Version: 1.5
Python Version: 2.7.2
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'coding',
 'south')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')


Traceback:
File "/Users/lukaskawerau/.virtualenvs/MMAD/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File "/Users/lukaskawerau/Dropbox/Coding/mmad/app/mmad/coding/views.py" in assignment
  179.             process_form(formset, request, current_page, paginator)
File "/Users/lukaskawerau/Dropbox/Coding/mmad/app/mmad/coding/views.py" in process_form
  36.             if form['relevance'] == False:

Exception Type: KeyError at /coding/assignment/1/
Exception Value: 'relevance'

我究竟做错了什么?我已经尝试了我能想到的一切,但没有任何效果。
非常感谢任何帮助!

更新: 我再次查看了本地变量,并注意到它form是空的:

formset <django.forms.formsets.CodingFormFormSet object at 0x10eb9dd10>
form    {}

为什么会这样?

更新 2: 问题完全不同:我使用的 JavaScript 插件弄乱了我输入的 HTML“名称”标签,所以 Django 只看到一个空表单。
我接受@Francis 的回答,因为它是最详细的并且仍然很有帮助。我的赏金也不应该浪费。
我们从中学到什么?检查你的 JS。

4

3 回答 3

3

我还没有在我的测试项目中设置这个例子,但是让我印象深刻的一个可能的问题是:

relevance = forms.NullBooleanField('relevance')

NullBooleanField allows NULL as one of the options。_ 我想知道表单是否看到 NULL/None 并从 clean_data 字典中删除键/值...

无论哪种方式,我都会调用表单的超级清洁方法并从那里开始......

def clean(self):
    #this line is kinda important
    cleaned_data = super(CodingForm, self).clean()

    event_date = cleaned_data.get("event_date")
    location = cleaned_data.get("location")

    if event_date and location:
        cleaned_data['relevance'] = True
        print cleaned_data["relevance"]
    else:
        cleaned_data['relevance'] = False

    return cleaned_data

另外像这样包装对 dict 元素的调用以防止关键错误

if 'relevance' in form:
    if form['relevance'] == False:
        ...
    elif form['relevance'] == True:
        ...

或者

try: 
    if form['relevance'] == False:
        ...
    elif form['relevance'] == True:
        ...
except KeyError, e:
    ...
于 2013-07-15T14:16:07.673 回答
0

你的 clean 方法有错误。它应该从

cleaned_data = super(CodingForm, self).clean()

就像文档中的示例一样。

于 2013-07-15T15:46:20.957 回答
0

它应该form.fields['relevance']代替form['relevance'].

于 2013-07-12T13:21:56.190 回答