在Pycharm中调试表单验证

sf6xfgos  于 2023-06-23  发布在  PyCharm
关注(0)|答案(2)|浏览(134)

我正在尝试使用Pycharm在Django中调试表单验证。我通过ImageField上传的图像验证表单失败了,我想找出它失败的原因。然而,每当我尝试调试验证过程并使用POST数据进入并完成表单初始化时,它甚至不尝试验证,并且在最后抛出错误,因为在尝试将表单数据保存到数据库时有空字段。快把我逼疯了...行为如何改变取决于我是否观察单个步骤?我还尝试设置了几个断点,例如。在BaseForm类的full-clean方法期间,它似乎永远不会到达那里。

**编辑:**这里是一些代码

我的模型&表单:

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

68bkxrlz1#

这是一个真实的的痛苦。这个问题我已经遇到两次了,但仍然没有找到好的解决办法。

这是覆盖表单的__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代码。
您可以在调试后保留或删除这些额外的代码-这不会产生显著的差异。但最好还是离开,以防将来你需要这个。
”””所以,这里到底发生了什么?**
(bugreport on Django project site: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 getter以在“Variables”窗口中显示其值。这会破坏正常的执行流程。
(This这就是为什么在这种情况下应该定义像get_error()这样的方法,而不是属性)
一个可能的建议是避免断点和在窗体的__init__方法内部的分步执行。但是如果您确实需要调试它,那么请修改代码,以便在逐步执行期间不存在_errors属性。这将阻止对full_clean方法的调用。PyCharm调试器每次尝试访问errors属性时都会收到错误。

注意errors属性可以在执行暂停时的任何一步进行求值,甚至可以在__init__方法之外。如果所有字段都已经完全初始化了,这可能不会影响结果(记住只在__init__方法中这样做)。但是,您可能会发现仍然无法调试表单验证过程,因为在到达is_valid方法调用之前,表单显示为已验证。在这种情况下,在full_clean方法内部设置一个断点,并且不要在窗体示例化点和该断点之间停止。

5fjcxozz

5fjcxozz2#

此问题也报告给JetBrains PyCharm,问题编号为PY-39729。

相关问题