7

我正在尝试使用 Pycharm 在 Django 中调试表单验证。我通过 ImageField 上传的图像验证我的表单失败,我想找出它失败的原因。但是,每当我尝试调试验证过程并使用 POST 数据进入并完成表单初始化时,它甚至都不会尝试验证,并且在尝试将表单数据保存到数据库。这让我发疯......行为如何根据我是否观察各个步骤而改变?我还尝试设置几个断点,例如在 BaseForm 类的完全清理方法期间,但它似乎永远不会到达那里。

编辑:这是一些代码

我的模型和形式:

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():
            ...
4

1 回答 1

6

这是一个真正的痛苦。我遇到过两次这个问题,仍然没有找到好的解决方案。

__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属性值的方法,以便errorsgetter 在重复调用时不会再次执行相同的工作。

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 调试器假定属性只是属性,它们不会对对象的内部状态进行关键更改。因此,当您调试方法时,调试器会调用errorsgetter 在“变量”窗口中显示它的值。__ini__这打破了正常的执行流程。

(这就是为什么你应该get_error()在这种情况下定义方法,而不是属性)

__init__一种可能的建议可能是避免在表单方法中设置断点和逐步执行。但是,如果您确实需要调试它,请修改代码,以便_errors在逐步执行期间不存在该属性。这将阻止对该full_clean方法的调用。PyCharm 调试器每次尝试访问该errors属性时都会收到错误消息。

注意errors可以在暂停执行时的任何步骤上评估该属性,即使在__init__方法之外也是如此。如果所有字段都已完全初始化,这可能不会影响结果(请记住__init__仅在方法中执行此操作)。但是,您可能会发现您仍然无法调试表单验证过程,因为在您到达is_valid方法调用之前表单似乎已验证。在这种情况下,在full_clean方法内部设置一个断点,并且不要在表单实例化点和这个断点之间停止。

于 2015-04-26T20:56:39.960 回答