2011-10-18 50 views
0

後有效我有一個很奇怪的問題與django的形式,我顯示形式,其中包括一個附加的formset使得用戶也可以爲在同一時間的外鍵關係提交數據。Django的形式僅是第二請求

模板總是顯示該原始模型和第二模型一種形式中的一種形式。

我現在要提交的兩種形式,而不在第二種形式中的任何填充。 在第一次提交時,seond表單不驗證,頁面重新顯示,但在第二次提交時,第二個表單有效!即使如此,POST數據也是一樣的。 這怎麼可能?

或者,也許我這樣做完全錯誤的,你怎麼能辨別或者如果用戶沒有在任何填寫表單集,如果他的東西充滿無效?

這裏的模型:

class Software(models.Model): 
    creation_date = models.DateTimeField(default=datetime.now) 
    creator = models.ForeignKey(User) 
    version = models.CharField(max_length=300, unique=True, editable=False) 
    major_version = models.IntegerField() 
    minor_version = models.IntegerField() 
    [...] 

    def save(self, **kwargs): 
     """ 
     This updates the version string to the combined representation. 
     """ 
     self.version = Software.combine_version_string (self.major_version, self.minor_version) 
     super(Software, self).save(**kwargs) 

class SoftwarePatch(models.Model): 
    file = models.FileField(upload_to='software_patches') 
    file_name = models.CharField(max_length=255, editable=False) 
    file_date = models.DateTimeField(default=datetime.now) 
    upload_date = models.DateTimeField(default=datetime.now) 
    software = models.ForeignKey('Software', related_name='patches') 
    firmware_patch = models.BooleanField(default=True) 
    target_path = models.CharField(max_length=255, blank=True) 

    class Meta: 
     unique_together = ('software', 'file_name') 
     verbose_name_plural = "software patches" 

    def __unicode__(self):   
     return self.file_name 

    def clean(self): 
      if self.file and not self.file_name: 
       self.file_name = self.file.file.name 

這裏我的形式:

SoftwarePatchFormSet = inlineformset_factory(Software, 
    SoftwarePatch, 
    extra=1) 


class SoftwareForm(forms.ModelForm): 
    """ 
    A simple form for creating a new software. 
    """ 
    class Meta: 
     model = Software 

最後我的看法功能:

def software_add(request, software_id=None): 
    if software_id == None: 
     software = Software() 
    else: 
     software = Software.objects.get(id=software_id) 

    if request.POST:   
     form = SoftwareForm(request.POST, instance=software)   

     if form.is_valid(): 
      software = form.save(commit=False) 
      softwarepatch_formset = SoftwarePatchFormSet(request.POST, request.FILES, instance=software) 

      if softwarepatch_formset.is_valid(): 
       software = form.save() 
       softwarepatch_formset.save() 

       # Redirect, in case of a popup close it 
       if request.POST.has_key("_popup"): 
        pk_value = software._get_pk_val() 
        return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \ 
         # escape() calls force_unicode. 
         (escape(pk_value), escape(software))) 
       if 'next' in request.POST: 
        return HttpResponseRedirect(request.POST['next']) 
       else: 
        return HttpResponseRedirect(reverse('index')) 
    else: 
     form = SoftwareForm(instance=software) 
     softwarepatch_formset = SoftwarePatchFormSet(instance=software) 

    is_popup = request.GET.has_key("_popup") or request.POST.has_key("_popup") 

    return render_to_response(
     'main/software_edit.html', 
     {'form': form, 
     'softwarepatch_formset': softwarepatch_formset, 
     'add': True, 
     'is_popup': is_popup, 
     }, 
     context_instance = RequestContext(request) 
    ) 

回答

0

好吧,我終於找到了我的問題!

我有以下模型字段:file_date = models.DateTimeField(缺省值= datetime.now)

這設置innital-文件日期到這樣一個值:u'2011-10-18 08: 14:30.242000' 通過HTML渲染窗口小部件的值將是後:u'2011-10-18 8點14分三十秒' 所以Django會覺得形式改變,因此無法保存。

在第二負載Django會自動設置截斷值作爲初始文件的日期,然後沒有什麼變化,如預期的那樣保存的作品。

所以現在我只需要弄清楚,而不是使用datetime.now什麼。當我弄明白這一點時,我會更新這篇文章。

+0

您可以添加'auto_add'或'auto_now_add' [https://docs.djangoproject.com/en/dev/ref/models/fields/#datefield]。請注意,該字段不會顯示在管理員或由「ModelForm」自動生成的表單中。否則刪除默認值,並在視圖中設置'request.POST [「field_date」]'如果用戶沒有輸入[在'softwarepatch_formset = SoftwarePatchFormSet(request.POST,request.FILES,instance = software)'之前'' –

+0

我現在接受我自己的答案,因爲我發現所述的問題。我爲有問題的datetime.now語句添加了一個單獨的問題http://stackoverflow.com/questions/7836005/django-datetimefield-has-problems-with-datetime-now – Fabian

1

首先,你應該只設置實例參數爲現有對象創建表單/表單集時,即已經存在於數據庫中的對象。因此,例如,如果software_id = None,它是一個GET請求,你應該只做form = SoftwareForm()

此外,在做software = form.save(commit=False)後,您應該做software.save()而不是software = form.save()。 [我認爲這不是一個真正的問題,只是你正在重做一次節省]。請記住,如果軟件模型中有ManyToManyField,則需要在software = form.save()之後執行form.save_m2m()

這就是我想你應該有:

def software_add(request, software_id=None): 
    if request.POST: 
     if software_id: 
      software = Software.objects.get(id=software_id) 
      form = SoftwareForm(request.POST, instance=software) 
     else: 
      form = SoftwareForm(request.POST) 

     if form.is_valid(): 
      software = form.save(commit=False) 
      softwarepatch_formset = SoftwarePatchFormSet(request.POST, request.FILES, instance=software) 

      if softwarepatch_formset.is_valid(): 
       software.save() 
       softwarepatch_formset.save() 

       # Redirect, in case of a popup close it 
       if request.POST.has_key("_popup"): 
        pk_value = software._get_pk_val() 
        return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \ 
         # escape() calls force_unicode. 
         (escape(pk_value), escape(software))) 
       if 'next' in request.POST: 
        return HttpResponseRedirect(request.POST['next']) 
       else: 
        return HttpResponseRedirect(reverse('index')) 
     else: 
      softwarepatch_formset = SoftwarePatchFormSet(request.POST, request.FILES)  
    else: 
     if software_id: 
      software = Software.objects.get(id=software_id) 
      form = SoftwareForm(instance=software) 
      softwarepatch_formset = SoftwarePatchFormSet(instance=software) 
     else: 
      form = SoftwareForm() 
      softwarepatch_formset = SoftwarePatchFormSet() 


    is_popup = request.GET.has_key("_popup") or request.POST.has_key("_popup") 

    return render_to_response(
     'main/software_edit.html', 
     {'form': form, 
     'softwarepatch_formset': softwarepatch_formset, 
     'add': True, 
     'is_popup': is_popup, 
     }, 
     context_instance = RequestContext(request) 
    ) 
+0

您好,感謝您的建議,但遺憾的是沒有解決我的問題。因爲我要救即便如此沒有software_patch是有史以來填充在軟件模型,這在某種程度上工作在管理後臺。在那裏你可以顯示例如三個項目的software_patch表單集,如果你不以任何人填補我仍然能夠保存。 – Fabian

+0

Btw。上面的代碼中有一個錯誤。如果軟件表單無效,您將嘗試通過'softwarepatch_formset':softwarepatch_formset,在結束時崩潰。 – Fabian

+0

對不起,沒有真正測試過。我糾正了它。 –