2012-08-27 25 views
4

我想用Pycharm在Django中調試表單驗證。通過ImageField上載的圖像驗證我的表單失敗,我想知道它爲什麼會失敗。但是,每當我嘗試調試驗證過程並進入並通過POST數據進行表單初始化時,它甚至不會嘗試驗證,並且在嘗試將表單數據保存到數據庫。這讓我瘋狂......行爲如何改變取決於我是否觀察到個別步驟?我也嘗試設置幾個斷點,例如在BaseForm類的完全清理方法期間,但它似乎永遠不會到達那裏。在Pycharm中調試表單驗證

編輯:下面是一些代碼

我的模型&形式:

class Car(models.Model): 
    ... 
    image = models.ImageField(upload_to='car_images/',blank=True,null=True) 

class CarForm(ModelForm): 
    class Meta: 
     model = Car 

筆者認爲:

def create_car(request): 
    if request.method == 'POST': 
     car_form = CarForm(request.POST,request.FILES) 
     if car_form.is_valid(): 
      ... 
+1

沒有你的代碼,沒有人能夠幫助你。 – Jingo

+0

我加了一些代碼 –

+0

你的表單是否有'enctype =「multipart/form-data」'? –

回答

3

這是一個真正的痛苦。我有兩次這個問題,仍然沒有找到好的解決方案。

這是一個安全調試的例子,當您覆蓋表單的__init__方法時。

class MyForm(forms.ModelForm): 

    def __init__(self, *args, **kwargs): 
     super(MyForm, self).__init__(*args, **kwargs) 

     # Disable form validation for debugging purposes unless the 
     # object is fully initialized. Set breakpoints BELOW this line. 
     del self._errors 

     # Write some additional initializations here, debug safely. 
     ... 

     # Initialization is finished. Enable form validation. 
     self._errors = None 

如果你要調試的基本形式類,然後以同樣的方式修補Django的代碼。

您可以在調試後離開或刪除這些額外的代碼 - 這並沒有太大的區別。但是最好留待你未來需要的情況。

那麼,這裏究竟發生了什麼?

(在Django項目現場錯誤報告:https://code.djangoproject.com/ticket/24710

看來問題是,Django的BaseForm.errors屬性getter(這是真的@property裝飾的方法)不會太多。它調用full_clean()方法,該方法更改_errors屬性值,以便errors getter在重複調用時不會再次執行相同的工作。

當然
class BaseForm(object): 

    @property 
    def errors(self): 
     if self._errors is None: 
      self.full_clean() 
     return self._errors 

    def full_clean(self): 
     self._errors = ErrorDict() 
     ... 

中PyCharm調試器假設性只是屬性,他們不這樣做的對象的內部狀態的關鍵變化。所以調試器在調試__ini__方法時調用errors獲取器在「變量」窗口中顯示它的值。這打破了正常的執行流程。

(這就是爲什麼你應該定義在這樣的情況下,不性能如get_error()方法)

一個可能的建議可能是避免斷點和一步一步執行窗體的__init__方法的內部。但是,如果您真的需要調試它,請修改代碼,以便在逐步執行過程中不存在_errors屬性。這將防止調用full_clean方法。 PyCharm調試器每次嘗試訪問errors屬性都會收到錯誤。

:所述errors屬性可在任何步驟進行評估時執行暫停時,外連__init__方法。如果所有字段已經完全初始化,這可能不會影響結果(請記住僅在__init__方法中執行此操作)。但是,您可能會發現仍然無法調試表單驗證過程,因爲表單在達到is_valid方法調用之前顯示爲有效。在這種情況下,在full_clean方法中設置斷點,並且不要在表單實例化點和此斷點之間停止。