I have a Django model with a customer_code field that is set to unique but only some users will have an assigned value for this field. Other users simply use this code to find the user who provided their code as a reference number. When they submit the form however it raises an error as the field is set to unique.
I would like to remove this error upon validation. The user does not get saved with the value it is set to None before save. I have tried doing this so far with a custom clean() method on the form:
def clean(self):
super(EmployeeForm, self).clean()
if 'customer_code' in self.errors:
del self._errors['customer_code']
return self
But this has not been working. All help is appreciated, thanks.
In the end of method you should return cleaned_data
cleaned_data = super(EmployeeForm, self).clean()
...
return cleaned_data
Related
Let's say I have a Django form with ChoiceField:
class MyForm(forms.Form):
name = forms.CharField(label="Name", required=True)
some_object = forms.ChoiceField(label="Object", choices=[(0, '-----')] + [(x.id, x.name) for x in Obj.objects.all()])
Choisefield is being initialized with list of objects headed by 'empty choice'. There is no object with pk=0.
In that form I have a clean() method:
def clean(self):
if not Obj.objects.filter(self.cleaned.data['some_object'].exists():
self.errors.update({'some_object': ['Invalid choice']})
It works well when I'm sending a form to a server, if data in it doesn't match conditions, field.is_valid returns False and I render form with error messages. But, when I create an empty form like this:
if request.method == 'GET':
data = {'name': 'Untitled',
'some_object': 0}
form = MyForm(data)
return render(request, 'app\template.html', {'form': form})
Django renders form with error message ('Invalid choice') even though form was just created and 'Object' select was intended to be set in empty position. Is it possible to disable form clean() method in specific cases? Or maybe I'm doing this all wrong? What is the best practice to create an empty form?
The problem is that a form with any data dictionary passed to it counts as a "bound" form, against which Django will perform data validation. See here for details: https://docs.djangoproject.com/en/2.1/ref/forms/api/#bound-and-unbound-forms
You want an "unbound" form - to have default initial values in here, just set the initial property on your form fields. See full details here: https://docs.djangoproject.com/en/2.1/ref/forms/fields/#initial
I have created a simple html form using models.Model in models.py, ModelForm in forms.py and oldschool Django templates (nothing fancy)
If a user inputs text in a number field and submits the form, the server returns a KeyError
Example: The following field 'height':
class DataRegistryPart2(models.Model):
height = models.SmallIntegerField(blank=True, null=True)
Will be displayed as a html input in the template:
<input id="id_height" name="height" type="number">
Im using custom validation in forms.py:
...
def clean(self):
cleaned_data = super(CreatePatient, self).clean()
height = cleaned_data["height"] # <-- This is where the KeyError happens!
If a user enters text or a decimal number in the input field and submits the html form, Django returns a KeyError.
How can I prevent this from happening (without using try/catch).
Thanx!
If you enter non-valid values into a field, that field is by definition not clean, so it will not be present in cleaned_data; hence the KeyError.
Unless you need this value to do some validation in combination with another field, you should do whatever you are doing in the specific clean_height method; this will only be called if the value passes the built-in field validation.
So I have a CreateView and it works 99% the way I want. If a user enters a letter in an integer field it tells the user to enter a number, if a user leaves a required field blank it tells them that they need to fill it in. This is all great, CreateView handles the errors for me. However, for obvious reasons, I am not letting the user create the slug field, this is created automatically by taking the date and two other fields combining them and slugifying them. If the user attempts to create a record that wouldn't result in a unique slug then the form is invalid but CreateView doesn't give any constructive feedback (unless you are in debug mode, then you get UNIQUE constraint failed).
If I add the code below to my CreateView, then I need to re-define all the error responses that CreateView was handling so nicely before.
def form_invalid(self, form):
return HttpResponse(#define stuff here)
Is there a way I can have CreateView handle invalid forms normally (as if I didn't have def form_invalid(self, form):) except for when there is a slug conflict?
You can do that by calling the parent's class version of form_invalid inside your overriding of form_invalid.
Example:
class MyCreateView(CreateView):
def form_invalid(self, form):
if my_condition: # Check whatever you want
return HttpResponse('reason it failed')
else: # Or call the parent class version
return super(MyCreateView, self).form_invalid(form)
I am writing a change password form, and I would like to pass the original password to the form for validation purposes, but the only way to do that is to make it a hidden field and pass it in with the rest of the data. I obviously don't want to do that, I'd rather just pass it to the form constructor from within the view, but if it's not passed in with the formdata then that won't work.
class MyForm(Form):
...
original_password = HiddenField()
...
def validate_current_password(form, field):
if field.data != form.original_password.data:
ERROR
form = MyForm(request.POST, original_password=password) Does not work unless request.POST is empty, or unless I actually render and submit the original password with the form. form.original_password.data is empty otherwise.
For those of you familiar with formencode's "state" variable, I solved this by subclassing Form and adding a state variable with information to assist in validation.
I'm trying to make a form that handles the checking of a domain: the form should fail based on a variable that was set earlier in another form.
Basically, when a user wants to create a new domain, this form should fail if the entered domain exists.
When a user wants to move a domain, this form should fail if the entered domain doesn't exist.
I've tried making it dynamic overload the initbut couldn't see a way to get my passed variabele to the clean function.
I've read that this dynamic validation can be accomplished using a factory method, but maybe someone can help me on my way with this?
Here's a simplified version of the form so far:
#OrderFormStep1 presents the user with a choice: create or move domain
class OrderFormStep2(forms.Form):
domain = forms.CharField()
extension = forms.CharField()
def clean(self):
cleaned_data = self.cleaned_data
domain = cleaned_data.get("domain")
extension = cleaned_data.get("extension")
if domain and extension:
code = whoislookup(domain+extension);
#Raise error based on result from OrderFormStep1
#raise forms.ValidationError('error, domain already exists')
#raise forms.ValidationError('error, domain does not exist')
return cleaned_data
Overriding the __init__ is the way to go. In that method, you can simply set your value to an instance variable.
def __init__(self, *args, **kwargs):
self.myvalue = kwargs.pop('myvalue')
super(MyForm, self).__init__(*args, **kwargs)
Now self.myvalue is available in any form method.
Do you have a model that stores the domains? If so, you want to use a ModelForm and set unique=True on whichever field stores the actual domain in the model. As of Django 1.2, you can even do any additional validation inside the model, rather than the form.