在 Pycharm 中调试表单验证 [英] Debugging form validation in Pycharm

查看:21
本文介绍了在 Pycharm 中调试表单验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to debug form validation in Django with Pycharm. Validation of my form fails at an image I upload via an ImageField and I want to find out why it's failing on it. However, whenever I try to debug the validation process and step into and through the form initialization with the POST data, it doesn't even try validating and at the end throws an error because of empty fields when trying to save the form data to the database. It is driving me nuts... how can the behavior change depending on whether I observe the individual steps or not? I also tried to set several break points, e.g. during the full-clean method of the BaseForm class, but it doesn't seem to ever get there.

这是一些代码

我的模型 &形式:

My model & form:

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

推荐答案

这真的很痛苦.我遇到了两次这个问题,仍然没有找到好的解决方案.

This is a real pain. I've got this problem twice, and still have not found good solution.

这是覆盖表单的 __init__ 方法时安全调试的示例.

This is an example of safe debugging when you override the form's __init__ method.

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 代码.

If you want to debug the base form classes then patch Django code in the same way.

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

You can either leave or remove this additional code after debugging - this does not make significant difference. But it's better to leave for the case you need this in the future.

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

(Django 项目站点上的错误报告:https://code.djangoproject.com/ticket/24710)

(bugreport on Django project site: https://code.djangoproject.com/ticket/24710)

问题似乎是 Django 的 BaseForm.errors 属性 getter(这实际上是一个带有 @property 装饰器的方法)做了太多事情.它调用 full_clean() 方法,该方法更改了 _errors 属性值,以便 errors getter 在重复调用时不会再次执行相同的工作.>

It seems the problem is that Django's BaseForm.errors property getter (which is really a method with @property decorator) does too much. It calls the full_clean() method which changes the _errors property value so that errors getter does not do same work again on repeating calls.

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 获取器以在变量"窗口中显示它的值.这打破了正常的执行流程.

Of course PyCharm debugger assumes that properties are just properties, and they do not do critical changes to the internal state of the objects. So the debugger calls the errors getter to show it's value in the "Variables" window when you debug the __ini__ method. And this breaks the normal execution flow.

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

(This is why you should define methods like get_error() in such cases, not properties)

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

One possible suggestion may be to avoid breakpoints and step-by-step execution inside of the form's __init__ method. But if you really need to debug it then modify the code so that the _errors property does not exist during the step-by-step execution. This will prevent calls to the full_clean method. PyCharm debugger will receive error each time it will try to access the errors property.

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

Note: the errors property may be evaluated on any step when execution is paused, even outside of the __init__ method. This probably will not affect the result if all fields are fully initialized already (remember to do this in the __init__ method only). However you may find that you still can not debug the form validation process because the form appears validated before you reach the is_valid method call. In this case set a breakpoint inside of the full_clean method, and don't stop between the form instantiation point and this breakpoint.

这篇关于在 Pycharm 中调试表单验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆