2013-07-12 53 views
1

所以我每次尝试提交表单时都会收到一个KeyError错误。
我在here之前问过类似的问题,该解决方案似乎工作了一段时间,但现在我得到了上面提到的KeyError。
代码及以下的足迹:Django - formset表单字段上的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> 

和Trace:

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。

+1

为变量'form = form.cleaned_data'使用一个不同的名字 – karthikr

+1

试过这个,但没有帮助,悲伤。 – LukasKawerau

回答

3

我还没有建立这个例子在我的测试项目,但东西,在我看来是一个可能的问题是这样的:

relevance = forms.NullBooleanField('relevance') 

NullBooleanFieldallows NULL as one of the options。不知形式看空/无,从cleaned_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: 
    ... 
1

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

+1

不幸的是,我然后得到'字典'没有属性'字段' – LukasKawerau

+1

对不起,我没有看到'form = form.cleaned_data',所以混乱。 –

0

您的清洁方法存在错误。它应该从

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

docs中的示例。