# Separating Validation Logic in Django Forms

**URL:** https://forum.djangoproject.com/t/separating-validation-logic-in-django-forms/24068
**Category:** Forms & APIs
**Created:** [September 22, 2023, 9:05pm UTC](https://forum.djangoproject.com/t/separating-validation-logic-in-django-forms/24068 "2023-09-22T21:05:45Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![yyango](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/yyango/32/15497_2.png) [@yyango](https://forum.djangoproject.com/u/yyango)
#### Post date: [September 22, 2023, 9:05pm UTC](https://forum.djangoproject.com/t/separating-validation-logic-in-django-forms/24068/1 "2023-09-22T21:05:45Z")

</div>

I’m attempting to centralize all form validation in a separate `validators.py` file and avoid performing any validation in `forms.py` or `views.py`. Is this considered a standard practice? I want to separate the validation for simplicity, but it seems like Django is making it difficult for me. I find it challenging to access the necessary data for validation, and the process feels more complex compared to typical Django conventions.

I intentionally want to avoid using `clean()` methods in `forms.py` because that would involve including validation in the forms module rather than the validators module. However, I’m unsure if I’m doing something wrong.

For instance, to access `request.user` for authentication validation in my specific case, I had to resort to an unwieldy solution I found on Stack Overflow to make it work:

```auto
def __init__ (self, *args, **kwargs):
    current_user = kwargs.pop('current_user', None)
    super(UploadFileForm, self). __init__ (*args, **kwargs)
    self.fields["is_public"].validators.append(validate_user_authentication(current_user))

def validate_user_authentication(current_user):
    def validate(value):
        if value and not current_user.is_authenticated:
            raise ValidationError("This field is only accessible to authenticated users.")
    return validate

```

Although I’m still unsure about the inner workings of this approach, it at least functions as intended.

Now, I’m facing a challenge with validating the number of files uploaded in my multi-upload feature. I’m unable to access the file count from `request.FILES.getlist("uploaded_files")` within the views module.

```auto
uploaded_files = MultipleFileField(
    required=True,
    allow_empty_file=False,
    validators=[
        validate_file_size,
        validate_number_of_files],
)

def validate_number_of_files(value):
    max_allowed_files = settings.MAX_FILE_COUNT
    if len(value) > max_allowed_files:
        raise ValidationError(f"Please upload a maximum of {max_allowed_files} files.")

```

The above approach doesn’t work because the literal file is being passed as the argument. How should I handle this situation? I would prefer not to continue modifying the ` __init__ ` method, which I barely understand.

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [September 23, 2023, 12:33am UTC](https://forum.djangoproject.com/t/separating-validation-logic-in-django-forms/24068/2 "2023-09-23T00:33:11Z")

</div>

> [@yyango](#):
>
> Is this considered a standard practice?

It’s definitely not.

It’s been my experience that the form-level validation is very specific to the form being validated. Rarely do I see two forms where all the validation is the same between them.

Having said that…

> [@yyango](#):
>
> I intentionally want to avoid using `clean()` methods in `forms.py` because that would involve including validation in the forms module rather than the validators module.

It’s not that you’re doing something “wrong”, it’s just that you’re not quite following this train of thought through to a conclusion.

Nothing prevents you from creating a library of “validation functions” - and then calling those functions from your form-level validation. In other words, if you have a `clean_user` function that needs to be called from multiple forms allowing for the entry of a `user` field, you could do something like:

```auto
from my_validators import my_clean_user

class MyForm(Form):
   ...
   def clean_user(self):
     return my_clean_user(self)

```

> [@yyango](#):
>
> For instance, to access `request.user` for authentication validation in my specific case, …

That’s pretty much how it’s done. (Well, I wouldn’t have done it quite that way. I would have attached `current_user` to `self`, allowing me to use `validate_user` directly without having to attach an additional function.)

(Why don’t you have access to `request` in a form? Because there’s no requirement for there to be a request object to be associated with a form. You can use forms to validate data being passed around your system under a variety of circumstances that don’t directly involve a request from a browser.)

> [@yyango](#):
>
> Now, I’m facing a challenge with validating the number of files uploaded in my multi-upload feature.

See the code example in the section [Uploading multiple files](https://docs.djangoproject.com/en/4.2/topics/http/file-uploads/#uploading-multiple-files).

My understanding from this (a bit of a guess here - I’ve not tried this) is that you could override `clean_upload_field`. Call super to get what the example refers to as `files` and interrogate it to see how many were supplied.
