I have a really simple form on which I’m doing some validation:
JavaScript
x
9
1
def clean(self):
2
cleaned_data = super().clean()
3
4
start = cleaned_data.get("start")
5
end = cleaned_data.get("end")
6
7
if start >= end:
8
raise ValidationError("start should not be greater than end.")
9
But I need to add another validation (which is based on the user making the request).
I tried to add the parameter to the clean method:
JavaScript
1
12
12
1
def clean(self, user):
2
cleaned_data = super().clean()
3
4
start = cleaned_data.get("start")
5
end = cleaned_data.get("end")
6
7
if start >= end:
8
raise ValidationError("start should not be greater than end.")
9
10
if not user.email.endswith("@example.com"):
11
raise ValidationError("blah...")
12
Unfortunately, I cannot call the is_valid() in the view with a parameter:
JavaScript
1
3
1
if form.is_valid(request.user):
2
.
3
I get the following error message:
is_valid() takes 1 positional argument but 2 were given
I also tried to add a new method to the form:
JavaScript
1
4
1
def validate_email(self, user):
2
if not user.email.endswith("@example.com")::
3
raise ValidationError("blah...")
4
and call it from the view:
JavaScript
1
5
1
if form.is_valid() and form.validate_email(request.user):
2
obj = form.save(commit=False)
3
obj.created_by = request.user
4
obj.save()
5
In that case, the exception really gets thrown and crashes the application.
My goals are:
- to make the validation dependant on a criteria in the request
- to display an error message normally when the validation fails
What would be the correct way to implement the custom validation ?
Advertisement
Answer
I would create a simple mixin class
JavaScript
1
4
1
class FormContextMixin:
2
def __init__(self, *args, **kwargs):
3
self.context = kwargs.pop("context", {})
4
super().__init__(*args, **kwargs)
and then use the FormContextMixin
class with your form class as
JavaScript
1
8
1
class AlbumModelForm(FormContextMixin, forms.ModelForm):
2
def clean(self):
3
user = self.context["request"].user
4
# doe something with `user`
5
6
class Meta:
7
fields = '__all__'
8
model = Album
Thus, you can initialize the form with any arbitrary data as
JavaScript
1
1
1
form = AlbumModelForm(request.POST, context={"request": request})