首页 > 解决方案 > 使用自定义验证器进行 Django 文件验证无法按预期工作

问题描述

我正在尝试制作一个包含一些数据和需要上传的文件的表单。我想将文件大小限制为 5MB,但我似乎不知道该怎么做。

我尝试使用 validators.py 文件并运行 .validate() 和 .run_validators() 但我没有让它工作。我将向您展示一些代码。

视图.py

from django.shortcuts import render
from .models import Oferta, CV
from django.contrib import messages

# Create your views here.
def incarcareoferta(req):
    context = {
        'title': "Incarcare oferta de munca | Best DAVNIC73"
    }
    if req.method == 'POST':
        try:
            COR = req.POST['COR']
            denumireMeserie = req.POST['denumireMeserie']
            locuri = req.POST['numarLocuri']
            agentEconomic = req.POST['agentEconomic']
            adresa = req.POST['adresa']
            dataExpirare = req.POST['expirareOferta']
            experientaSolicitata = req.POST['experienta']
            studiiSolicitate = req.POST['studii']
            judet = req.POST['judet']
            telefon = req.POST['telefon']
            emailContact = req.POST['email']
            cerere = Oferta(solicitant=req.user, cor=COR, denumireMeserie=denumireMeserie, locuri=locuri, agentEconomic=agentEconomic, adresa=adresa, dataExpirare=dataExpirare, experientaSolicitata=experientaSolicitata, studiiSolicitate=studiiSolicitate, judet=judet, telefon=telefon, emailContact=emailContact)
            cerere.save()
        except:
            messages.error(req, 'Nu ai completat corect campurile sau unul din ele este liber!')            
    return render(req, "../templates/pagini/incarcare-oferta-de-munca.html", context)

def incarcarecv(req):
    context = {
        'title': "Incarcare CV | Best DAVNIC73"
    }
    if req.method == 'POST':
        try:
            nume = req.POST['nume']
            prenume = req.POST['prenume']
            telefon = req.POST['telefon']
            email = req.POST['email']
            cv = req.FILES['CV']
            try:
                cv_upload = CV(
                solicitant=req.user,
                nume=nume,
                prenume=prenume,
                telefon=telefon,
                emailContact=email
                )
                CV.run_validators()
                cv_upload.CV.save(cv.name, cv)
                cv_upload.save()
            except (ValueError):
                messages.error(req, 'Formularul nu a fost incarcat!')
                messages.info(req, 'Verifica daca esti logat, sau daca ai completat campurile corect!')
            except:
                messages.error(req, 'Formularul nu a fost incarcat. Ceva nu a functionat corect!')
        except:
            messages.error(req, 'Nu ai completat corect campurile sau unul din ele este liber!')
    return render(req, "../templates/pagini/incarcare-cv.html", context)

验证器.py

from django.core.exceptions import ValidationError


def validate_file_size(value):
    filesize=value.size

    if filesize > 524288000:
        print('too big')
        raise ValidationError(_('Invalid value'), code='invalid')
    else:
        return value

模型.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=12)
    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)
    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)
    CV = 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.CV)

但它什么也没做。我也试过

from django.shortcuts import render
from .models import Oferta, CV
from django.contrib import messages

# Create your views here.
def incarcareoferta(req):
    context = {
        'title': "Incarcare oferta de munca | Best DAVNIC73"
    }
    if req.method == 'POST':
        try:
            COR = req.POST['COR']
            denumireMeserie = req.POST['denumireMeserie']
            locuri = req.POST['numarLocuri']
            agentEconomic = req.POST['agentEconomic']
            adresa = req.POST['adresa']
            dataExpirare = req.POST['expirareOferta']
            experientaSolicitata = req.POST['experienta']
            studiiSolicitate = req.POST['studii']
            judet = req.POST['judet']
            telefon = req.POST['telefon']
            emailContact = req.POST['email']
            cerere = Oferta(solicitant=req.user, cor=COR, denumireMeserie=denumireMeserie, locuri=locuri, agentEconomic=agentEconomic, adresa=adresa, dataExpirare=dataExpirare, experientaSolicitata=experientaSolicitata, studiiSolicitate=studiiSolicitate, judet=judet, telefon=telefon, emailContact=emailContact)
            cerere.save()
        except:
            messages.error(req, 'Nu ai completat corect campurile sau unul din ele este liber!')            
    return render(req, "../templates/pagini/incarcare-oferta-de-munca.html", context)

def incarcarecv(req):
    context = {
        'title': "Incarcare CV | Best DAVNIC73"
    }
    if req.method == 'POST':
        try:
            nume = req.POST['nume']
            prenume = req.POST['prenume']
            telefon = req.POST['telefon']
            email = req.POST['email']
            cv = req.FILES['CV']
            try:
                cv_upload = CV(
                solicitant=req.user,
                nume=nume,
                prenume=prenume,
                telefon=telefon,
                emailContact=email
                )
                cv_upload.CV.save(cv.name, cv)
                cv_upload.save()
            except (ValueError):
                messages.error(req, 'Formularul nu a fost incarcat!')
                messages.info(req, 'Verifica daca esti logat, sau daca ai completat campurile corect!')
            except (invalid):
                messages.error(req, 'File is too big!')
            except:
                messages.error(req, 'Formularul nu a fost incarcat. Ceva nu a functionat corect!')
        except:
            messages.error(req, 'Nu ai completat corect campurile sau unul din ele este liber!')
    return render(req, "../templates/pagini/incarcare-cv.html", context)

因为我认为错误将来自 validators.py

没有任何效果。

那么如何使用此代码限制文件大小?我现在做错了什么?谢谢。

标签: pythondjango

解决方案


正如验证器文档 [Django-doc]所说:

(...) 请注意,当您保存模型时验证器不会自动运行,但如果您使用 a ModelForm,它将在表单中包含的任何字段上运行您的验证器。(...)

Model.full_clean(..)您可以通过调用[Django-doc]手动验证您的模型:

try:
    cv_upload = CV(
        solicitant=req.user,
        nume=nume,
        prenume=prenume,
        telefon=telefon,
        emailContact=email
    )
    cv_upload.CV.save(cv.name, cv)
    cv_upload.full_clean()
    cv_upload.save()
except (ValueError):
    messages.error(req, 'Formularul nu a fost incarcat!')
    messages.info(req, 'Verifica daca esti logat, sau daca ai completat campurile corect!')
except (invalid):
    messages.error(req, 'File is too big!')
except:
    messages.error(req, 'Formularul nu a fost incarcat. Ceva nu a functionat corect!')

但我真的建议在这里使用ModelForm[Django-doc]。模型表单更容易管理,这些删除了大量的样板,此外,如果表单无效,这些将返回一批错误,而不是一个错误。


推荐阅读