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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With