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

查看:184
本文介绍了在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

我的观点:

  def create_car(request):
如果request.method =='POST':
car_form = CarForm(request.POST,request.FILES)
如果car_form.is_valid():
...


解决方案

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



这是一个例子,当你覆盖窗体的 __ init __ 方法。

  class MyForm(forms.ModelForm):

def __init __(self,* args,** kwargs):
super(MyForm,self).__ init __(* args,** kwargs)

#禁用表单验证用于调试目的,除非
#对象被完全初始化。在此行之下设置断点。
del self._errors

#在这里编写一些其他初始化,安全调试。
...

#初始化完成。启用表单验证。
self._errors =无

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



您可以在调试后离开或删除此附加代码 - 这并没有显着差异。但是最好在今后需要这种情况下离开。



那么这里真的发生了什么?



(Django项目网站上的bugreport: https://code.djangoproject .com / ticket / 24710



似乎问题是Django的 BaseForm.errors 属性getter(这是一个真正的方法, @property decorator)太多了。它调用 full_clean()方法,该方法更改 _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 __ 方法时,调试器调用错误 getter在变量窗口中显示它的值。这就打破了正常的执行流程。



(这就是为什么你应该像这样定义 get_error()案例而不是属性)



一个可能的建议可能是避免在窗体的 __ init __ 方法。但是,如果您真的需要调试它,然后修改代码,以便在逐步执行期间不存在 _errors 属性。这将阻止调用 full_clean 方法。 PyCharm调试器每次尝试访问错误属性时会收到错误。



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


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.

Edit: Here is some code

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

My View:

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.

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

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.

So, what is really going on here?

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

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

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.

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

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.

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天全站免登陆