在Pycharm中调试表单验证

Se *_*orm 6 django django-forms pycharm

我正在尝试使用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
Run Code Online (Sandbox Code Playgroud)

我的看法:

def create_car(request):
    if request.method == 'POST':
        car_form = CarForm(request.POST,request.FILES)
        if car_form.is_valid():
            ...
Run Code Online (Sandbox Code Playgroud)

raa*_*cer 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
Run Code Online (Sandbox Code Playgroud)

如果要调试基本表单类,则以相同方式修补Django代码.

您可以在调试后保留或删除此附加代码 - 这不会产生显着差异.但是最好留下你将来需要它的情况.

那么,这里到底发生了什么?

(Django项目网站上的bug报告: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()
        ...
Run Code Online (Sandbox Code Playgroud)

当然,PyCharm调试器假定属性只是属性,并且它们不会对对象的内部状态进行重要更改.因此,errors当您调试__ini__方法时,调试器会调用getter以在"Variables"窗口中显示它的值.这打破了正常的执行流程.

(这就是为什么你应该定义类似get_error()情况的方法,而不是属性)

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

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