2012-07-20 51 views
3

我想創建一個自定義清理方法,它在db中查看某個特定數據的值是否已經存在,如果是,則會引發錯誤。 我正在使用從其他類(項目)繼承的類(子系統)的模型形式。 我想檢查sybsystem是否已經存在或沒有,當我嘗試在表單中添加一個新的。Django:通過以模型形式查詢數據庫來驗證數據(使用自定義清理方法)

我在我的視圖函數中獲取項目名稱。

class SubsytemForm(forms.ModelForm): 

    class Meta: 
     model = Subsystem 
     exclude = ('project_name') 

    def clean(self,project_name): 

     cleaned_data = super(SubsytemForm, self).clean(self,project_name) 
     form_subsystem_name = cleaned_data.get("subsystem_name") 

     Subsystem.objects.filter(project__project_name=project_name) 
     subsystem_objects=Subsystem.objects.filter(project__project_name=project_name) 
     nb_subsystem = subsystem_objects.count() 

     for i in range (nb_subsystem): 
      if (subsystem_objects[i].subsystem_name==form_subsystem_name): 
       msg = u"Subsystem already existing" 
       self._errors["subsystem_name"] = self.error_class([msg]) 

      # These fields are no longer valid. Remove them from the 
      # cleaned data. 
      del cleaned_data["subsystem_name"] 
     return cleaned_data 

我的看法功能:

def addform(request,project_name): 
    if form.is_valid(): 
     form=form.save(commit=False) 
     form.project_id=Project.objects.get(project_name=project_name).id 
     form.clean(form,project_name) 
     form.save() 

這不是工作,我不知道該怎麼辦。 我有錯誤:乾淨的()到底需要2個參數(1給出)

我的模型:

class Project(models.Model): 
project_name = models.CharField("Project name", max_length=20) 

Class Subsystem(models.Model): 
subsystem_name = models.Charfield("Subsystem name", max_length=20) 
projects = models.ForeignKey(Project) 
+0

某種類型的堆棧跟蹤的可能是有用的。此外,我不確定是否可以從cleared_data數組中刪除密鑰。也許只是將其設置爲空或空字符串?然後在你的is_valid方法中,將project_name添加到form.clean方法中,但是我沒有看到它在代碼中的任何位置被定義? – 2012-07-20 12:56:33

+0

這只是一個錯誤。我想檢查表單中輸入的子系統名稱是否已被使用,因爲它必須是唯一的。 – user1507156 2012-07-20 13:02:18

+0

我使用is_valid方法,它是由django提供的默認方法來檢查數據是否正確 – user1507156 2012-07-20 13:47:09

回答

10

這段代碼有很多錯誤。

首先,你不應該顯式地調用clean。當您撥打form.is_valid()時,Django會自動爲您提供幫助。而且因爲它是自動完成的,所以你不能傳遞額外的參數。您需要在實例化表單時傳遞參數,並將其作爲乾淨代碼可引用的實例變量保存。其次,代碼實際上只驗證單個字段。所以應該在特定的clean_fieldname方法中完成 - 即clean_subsystem_name。這樣可以避免在最後使用_errors和刪除不需要的數據。第三,如果你發現自己得到了一些東西,迭代一個範圍,然後使用該索引指向原始列表,那麼你做錯了。在Python中,你應該總是迭代你感興趣的實際事物 - 在這種情況下是queryset。但是,在這種情況下,這是無關緊要的,因爲你應該直接在數據庫中查詢實際名稱並檢查是否它存在,而不是迭代檢查匹配。

所以,把他們放在一起:

class SubsytemForm(forms.ModelForm): 

    class Meta: 
     model = Subsystem 
     exclude = ('project_name') 

    def __init__(self, *args, **kwargs): 
     self.project_name = kwargs.pop('project_name', None) 
     super(SubsystemForm, self).__init__(*args, **kwargs) 

    def clean_subsystem_name(self): 
     form_subsystem_name = self.cleaned_data.get("subsystem_name") 

     existing = Subsystem.objects.filter(
         project__project_name=self.project_name, 
         subsytem_name=form_subsystem_name 
        ).exists() 

     if existing: 
      raise forms.ValidationError(u"Subsystem already existing") 

     return form_subsystem_name 
+0

非常感謝。我想我明白我的錯誤,但它仍然不起作用!事實上,它沒有得到project_name,它只是將project_name設置爲None。任何想法 ? – user1507156 2012-07-23 12:27:36

+0

那麼,你已經從窗體中排除了'project_name'。但我不明白'project_name'和'subsystem_name'之間的關係。哪個是實際的型號字段名稱? – 2012-07-23 12:35:56

+0

我在問題中添加了模型。我從表單中排除了project_name,因爲我不希望用戶選擇與子系統映射哪個項目。我在我看來映射它。我認爲最好的辦法不是排除project_name,而是在我的表單中使用值初始化它(使用queryset填充project_name字段?)。我將這個字段設置爲隱藏。你怎麼看 ? – user1507156 2012-07-23 13:29:41

0

當你做形式= form.save(提交= FALSE)你存儲在一個子系統實例SubsystemForm中定義了變量形式,但是乾淨的方法。不是嗎?

+0

是的,我這樣做是爲了將我的子系統實例映射到項目。 – user1507156 2012-07-20 13:42:20

+0

但用form.clean(form,project_name)你不是調用你在SubsystemForm中定義的乾淨方法 – Pascal 2012-07-20 13:46:12

+0

那麼我應該怎麼做? – user1507156 2012-07-20 13:54:36

相關問題