Octavian Niculescu
Octavian Niculescu

Reputation: 445

Entry gets into the DB even if an exception is thrown

So I have a form which takes some input and a file field. I'm using a validator on the file filed to check for the size of the file. It is working well because I get the error on the page saying that the file is too large, but the entry still gets into the DB.

I don't know why this happens. I supposed that raising an exception would do the trick in my case, but it does not. 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 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)

validators.py

from django.core.exceptions import ValidationError


def validate_file_size(value):
    filesize=value.size

    if filesize > 1:
         raise ValidationError("Fisierul poate avea maxim 5MB.")
    else:
        return value

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

# Create your views here

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:
                if(req.user.is_authenticated):
                    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()
                    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!')
            except (ValueError):
                messages.error(req, 'Formularul nu a fost incarcat!')
                messages.info(req, 'Verifica daca esti logat!')
        except:
            messages.error(req, 'Nu ai completat corect campurile sau unul din ele este liber!')
            messages.info(req, 'Ai grija ca toate campurile sa fie completate si ca fisierul sa nu depaseasca 5MB!')
    return render(req, "../templates/pagini/incarcare-cv.html", context)

html file

{% extends 'base.html' %}
{% load static %}
{% block content %}
            <div class="container container-centru">
                <h1 class="heading-contact">Incarca CV</h1>
                {% include 'partials/_alerts.html' %}
                <form action="{% url 'incarcarecv' %}" method="POST" class="form-contact"  enctype="multipart/form-data">
                    {% csrf_token %}
                        <div class="form-group">
                            <label for="inputnume" class="email-contact">Nume</label>
                            <input type="text" name="nume" class="form-control" id="inputnume" aria-describedby="numeHelp" placeholder="Introdu nume">
                        </div>
                        <div class="form-group">
                                <label for="inputprenume" class="email-contact">Prenume</label>
                                <input type="text" name="prenume" class="form-control" id="inputprenume" aria-describedby="prenumeHelp" placeholder="Introdu prenume">
                        </div>
                        <div class="form-group">
                            <label for="inputtelefon" class="email-contact">Telefon</label>
                            <input type="text" name="telefon" class="form-control" id="inputtelefon" aria-describedby="telefonHelp" placeholder="Introdu telefon">
                        </div>
                        <div class="form-group">
                            <label for="inputemail" class="email-contact">Email</label>
                            <input type="email" name="email" class="form-control" id="inputemail" aria-describedby="emailHelp" placeholder="Introdu email">
                        </div>
                        <div class="form-group">
                                <label for="inputcv" class="email-contact">CV</label>
                                <input type="file" name="CV" accept=".docx,.doc,.pdf,application/msword" class="form-control" id="inputemail" aria-describedby="CVHelp">
                            </div>
                        <div class="form-group form-group-custom">
                                <input type="submit" value="Trimite" class="btn btn-secondary btn-block btn-login-custom">
                                <input type="submit" value="Resetează câmpurile" class="btn btn-secondary btn-block btn-reset-custom">
                        </div>                   
                </form>
            </div>
            <script src="{% static 'javascript/clearMessage.js' %}"></script>                  
{% endblock %}

So how can I make the post not enter the DB if the exception is thrown? Right now I get the error, but it is still entering the DB. (I can see it in the administration zone of django)

////edit: I deleted everything that was not about my problem from the code. ////edit2: added the HTML file

Upvotes: 0

Views: 34

Answers (1)

William Bright
William Bright

Reputation: 535

In Django, the typical workflow is to first run validators to verify that the data you are trying to commit into the database is "clean" and only then should one call save(). But due to some quirks calling save does not automatically clean the data.

so the workflow should be something along the lines of:

...
cv_upload = CV(solicitant=req.user, nume=nume, prenume=prenume, 
               telefon=telefon, emailContact=email)
# call clean before saving as we only want CLEAN data in the DB 
cv_upload.full_clean()
# now that it is relatively clean with Django's validators and our custom validators
# go ahead and save it
cv_upload.save()
...

Upvotes: 1

Related Questions