Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding custom validation to a field, for the generic view CreateView

The problem

Add custom validation to a form field in Django 1.3, the form is created by the generic view CreateView.

The model

class Picture(models.Model):
    file = models.ImageField(upload_to=get_image_path)
    filename = models.CharField(max_length=50, blank=True)
    user = models.ForeignKey(User, editable=False)
    upload_date = models.DateTimeField(auto_now_add=True,editable=False)

Generic view CreateView, a bit modified

class PictureCreateView(CreateView):
    model = Picture

    def clean_file(self,form):
        if image:
            if image._size > settings.MAX_IMAGE_SIZE:
                raise ValidationError("Image file too large ( > 20mb )")
        else:
             raise ValidationError("Couldn't read uploaded image")

    def get_form(self, form_class):
        form = super(PictureCreateView, self).get_form(form_class)
        form.instance.user = self.request.user
        return form

    def form_invalid(self, form):
        ...omitted none important code...
        response = JSONResponse(data, {}, response_mimetype(self.request))
        response['Content-Disposition'] = 'inline; filename=files.json'
        return response

    # Called when we're sure all fields in the form are valid
    def form_valid(self, form):
        ...omitted none important code...
        response = JSONResponse(data, {}, response_mimetype(self.request))
        response['Content-Disposition'] = 'inline; filename=files.json'
        return response

My question is: How can I do custom validation on the file field, before form_valid() is reached?

In short, what I've done so far

According to the documentation here - https://docs.djangoproject.com/en/dev/ref/forms/validation/ I should be able to override the file fields form validator, which I'm trying to do with clean_file() "The clean_() method in a form subclass - where is replaced with the name of the form field attribute. " This would have been easy if I had created the form manually, but it's created by Django from the model by the generic view.

My current solution, which is a ugly hack: You can see that I've overridden form_valid() and form_invalid(), in form_valid() I now call clean_file() and if it's a error I call form_invalid(). This creates a few problems, for example I need to create the error message response manually.

like image 412
james Avatar asked Mar 17 '12 10:03

james


People also ask

What does CreateView do in django?

CreateView. A view that displays a form for creating an object, redisplaying the form with validation errors (if there are any) and saving the object. This view inherits methods and attributes from the following views: django.

How does UpdateView work django?

UpdateView refers to a view (logic) to update a particular instance of a table from the database with some extra details. It is used to update entries in the database, for example, updating an article at geeksforgeeks.

How do I create a custom validation in HTML?

Use setCustomValidity() to set the message of the input affected to override the default message when the form is submitted. See the updated fiddle. As you can see in the fiddle, all you have to do is add an attribute data-equal-id wherein the attribute value must be the ID of password input element to be tested.

What is Form_class in Django?

Hi Christopher 'form_class' is used in Django Class Based to depict the Form to be used in a class based view. See example in the docs: https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-editing/


1 Answers

Why not create your modelform ?

from django import forms

class PictureForm(forms.ModelForm):
    def clean_file(self,form):
        if image:
            if image._size > settings.MAX_IMAGE_SIZE:
                raise ValidationError("Image file too large ( > 20mb )")
        else:
            raise ValidationError("Couldn't read uploaded image")

    class Meta:
        model = Picture

Then you could use it in your view with the form_class attribute:

class PictureCreateView(CreateView):
    form_class = PictureForm

    # .... snip
like image 110
jpic Avatar answered Sep 30 '22 09:09

jpic