Как использовать пользовательский метод проверки, принимающий параметры запроса

#python #django #django-forms

#python #django #django-forms

Вопрос:

У меня есть действительно простая форма, в которой я выполняю некоторую проверку:

 def clean(self):
    cleaned_data = super().clean()

    start = cleaned_data.get("start")
    end = cleaned_data.get("end")

    if start >= end:
        raise ValidationError("start should not be greater than end.")
 

Но мне нужно добавить еще одну проверку (которая основана на том, что пользователь делает запрос).

Я попытался добавить параметр в метод clean:

 def clean(self, user):
    cleaned_data = super().clean()

    start = cleaned_data.get("start")
    end = cleaned_data.get("end")

    if start >= end:
        raise ValidationError("start should not be greater than end.")

    if not user.email.endswith("@example.com"):
        raise ValidationError("blah...")
 

К сожалению, я не могу вызвать is_valid() в представлении с параметром:

 if form.is_valid(request.user):
   ....
 

Я получаю следующее сообщение об ошибке:

is_valid() принимает 1 позиционный аргумент, но было задано 2

Я также попытался добавить новый метод в форму:

 def validate_email(self, user):
    if not user.email.endswith("@example.com")::
        raise ValidationError("blah...")
 

и вызовите его из представления:

 if form.is_valid() and form.validate_email(request.user):
    obj = form.save(commit=False)
    obj.created_by = request.user
    obj.save()
 

В этом случае исключение действительно генерируется и завершает работу приложения.

Мои цели:

  • чтобы сделать проверку зависимой от критериев в запросе
  • для обычного отображения сообщения об ошибке при сбое проверки

Каков был бы правильный способ реализации пользовательской проверки?

Ответ №1:

Я бы создал простой класс mixin

 class FormContextMixin:
    def __init__(self, *args, **kwargs):
        self.context = kwargs.pop("context", {})
        super().__init__(*args, **kwargs) 

а затем используйте FormContextMixin класс с вашим классом form как

 class AlbumModelForm(FormContextMixin, forms.ModelForm):
    def clean(self):
        user = self.context["request"].user
        # doe something with `user`

    class Meta:
        fields = '__all__'
        model = Album 

Таким образом, вы можете инициализировать форму любыми произвольными данными как

 form = AlbumModelForm(request.POST, context={"request": request})