I've been trying to implement a file size validator in django on a filefield, but I can't really make it work.
Everything works right until I add this validator. After I add it, I can't upload files anymore at all. The error says "File field does not have a full_clean attribute".
views.py
from django.shortcuts import render, get_object_or_404
from .models import Oferta, CV
from django.contrib import messages
from django.core.paginator import Paginator
def incarcarecv(req):
context = {
'title': "Incarcare CV | Best DAVNIC73"
}
if req.method == 'POST':
nume = req.POST['nume']
prenume = req.POST['prenume']
telefon = req.POST['telefon']
email = req.POST['email']
cv = req.FILES['CV']
if(req.user.is_authenticated):
cv_upload = CV(
solicitant=req.user,
nume=nume,
prenume=prenume,
telefon=telefon,
emailContact=email
)
cv_upload.CVFile.full_clean()
cv_upload.CVFile.save(cv.name, cv)
cv_upload.save()
req.user.profile.cvuri.append(cv_upload.id)
req.user.profile.save()
messages.success(req, 'CV depus cu succes!')
else:
messages.error(req, 'Trebuie sa fii logat pentru a depune CV-ul!')
return render(req, "../templates/pagini/incarcare-cv.html", context)
models.py
from django.db import models
from django.contrib.auth.models import User
from .validators import validate_file_size
# Create your models here.
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
dataSolicitare = models.DateField(auto_now_add=True)
cor = models.CharField(max_length=25)
denumireMeserie = models.CharField(max_length=12)
locuri = models.IntegerField()
agentEconomic = models.CharField(max_length=50)
adresa = models.CharField(max_length=150)
dataExpirare = models.DateField()
experientaSolicitata = models.CharField(max_length=200)
studiiSolicitate = models.CharField(max_length=200)
judet = models.CharField(max_length=20)
localitate = models.CharField(max_length=25)
telefon = models.CharField(max_length=12)
emailContact = models.EmailField(max_length=40)
rezolvata = models.BooleanField(default=False)
def __str__(self):
return self.cor
class CV(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
dataUploadCV = models.DateField(auto_now_add=True)
nume = models.CharField(max_length=12)
prenume = models.CharField(max_length=12)
telefon = models.CharField(max_length=12)
emailContact = models.EmailField(max_length=40)
CVFile = models.FileField(upload_to='documents/%d/%m/%Y', validators=[validate_file_size])
rezolvata = models.BooleanField(default=False)
def __str__(self):
return self.nume + " " + self.prenume + ": " + str(self.CVFile)
validators.py
from django.core.exceptions import ValidationError
def validate_file_size(value):
filesize=value.size
if filesize > 5000000:
raise ValidationError("Maximum 5MB!")
I just can't seem to get why. Can you help me fix my code? As far as I know, .full_clean() runs some default django validators + the ones set in the model.
But actually it does not work.
Exception Value:
'FieldFile' object has no attribute 'full_clean'
Can you explain to me why is this happening and how can I make my validator run?
Thanks.
//by the way, someone recommended to change the order of the lines like this -
cv_upload.CVFile.save(cv.name, cv)
cv_upload.CVFile.full_clean()
but it does not work anyway.
1 Answer
As the error says, full_clean() isn't a method of a model field. It's a method of the model itself.
cv_upload.full_clean() works.
But you should just initialise your cv_upload with the file directly:
cv_upload = CV(
solicitant=...,
...,
CVFile=cv)
then you don't have to save the file separately, see the docs.
Also, you're running full_clean() but not catching any exceptions. What happens if validation fails? A ValidationError will be thrown. If you don't catch it, your view will return a HTTP 500 error (it will just crash).
So wrap it in a try ... except clause:
try:
cv_upload.full_clean()
except ValidationError as e:
messages.error(request, e)
else:
cv_upload.save()
messages.success(request, "yeah!")