2011-10-18 5 views
0

장고 양식과 관련하여 매우 이상한 문제가 있습니다. 사용자가 외래 키 관계에 대한 데이터를 동시에 제출할 수 있도록 추가 formset을 포함하는 양식을 표시합니다.Django 양식은 두 번째 요청 후에 만 ​​유효합니다.

템플릿은 항상 원래 모델의 양식과 두 번째 모델의 양식을 표시합니다.

두 번째 양식을 작성하지 않고 두 양식을 제출하고 싶습니다. 첫 번째 제출시 seond 양식의 유효성을 검사하지 않고 페이지를 다시 표시하지만 두 번째 제출시 두 번째 양식은 유효합니다! 그렇더라도 POST 데이터는 동일합니다. 어떻게 가능합니까?

어쩌면 내가 완전히 잘못하고있는 중입니다. 사용자가 formset에서 아무 것도 기입하지 않았거나 무언가를 잘못 입력 한 경우 어떻게 분별할 수 있습니까? 여기

모델 :

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 08:14:30' 따라서 장고는 양식이 변경되어 저장되지 않는다고 생각합니다.

두 번째로드에서 django는 자동으로 잘라낸 값을 초기 파일 날짜로 설정하고 아무 것도 변경되지 않고 저장이 예상대로 작동합니다.

이제는 datetime.now 대신 무엇을 사용해야하는지 알아야합니다. 나는 그것을 알아 냈을 때이 게시물을 업데이트 할 것이다.

+0

'auto_add' 또는'auto_now_add' [https://docs.djangoproject.com/en/dev/ref/models/fields/#datefield]를 추가 할 수 있습니다. 그러나 필드는 admin 또는'ModelForm'에 의해 자동 생성 된 폼에 표시되지 않습니다. 그렇지 않으면 기본값을 제거하고 사용자가 값을 입력하지 않으면 view의'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

첫째, 당신은 인스턴스 만 인수를 설정해야합니다 기존 객체 (즉, DB에 이미있는 객체)에 대한 양식/formset을 만들 때. 예를 들어 software_id = None이고 GET 요청 인 경우 form = SoftwareForm() 만 사용해야합니다.

또한 software = form.save(commit=False)을 수행 한 후 software = form.save() 대신 software.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 formset에 대해 세 개의 항목이 있는데 그 중 하나라도 입력하지 않으면 여전히 저장할 수 있습니다. – Fabian

+0

Btw.위의 코드에 오류가 있습니다. 소프트웨어 양식이 유효하지 않은 경우 충돌이 발생한 끝에 'softwarepatch_formset': softwarepatch_formset을 전달하려고 시도합니다. – Fabian

+0

죄송합니다. 실제로 테스트하지 않았습니다. 나는 그것을 바로 잡았다. –

관련 문제