Search code examples
djangodjango-modelsdjango-1.4imagefield

Django - How to Save ImageField Even if Form is Not Valid


I have a fairly standard model and form. I have some mandatory fields with an ImageField. When the user choose an image and doesn't field the mandatory fields, the image isn't saved and the user needs to 're-upload' it again.

As the row in the database already exists (because this form is part of a 'wizard'), I don't mind saving the picture in the database even if all the form isn't valid with all the mandatory data.

This is what I have right now in my view, which works when you fill all the mandatory fields:

def my_view(request):
    instance = MyModel.objects.get(user=request.user)
    form = MyForm(instance=instance)

    if request.POST:
        form = MyForm(request.POST, request.FILES, instance=instance)
        if form.is_valid():
            new_instance = form.save(commit=False)

            if request.FILES and request.FILES['photo']:
                uploaded_photo = request.FILES['photo']
                new_instance.photo = uploaded_photo

            new_instance.save()
            return HttpResponseRedirect(reverse('new_url'))

    return render_to_response('current_template.html', locals(), context_instance=RequestContext(request))

Here's what I tried to save the picture in DB even if the other fields aren't filled, but I get the error Django Upload Error - Upload a valid image (either not an image or corrupted):

def my_view(request):
    instance = MyModel.objects.get(user=request.user)
    form = MyForm(instance=instance)

    if request.POST:
        form = MyForm(request.POST, request.FILES, instance=instance)

        if request.FILES and request.FILES['photo']:
            uploaded_photo = request.FILES['photo']
            instance.photo = uploaded_photo
            instance.save()

        if form.is_valid():
            new_instance = form.save()
            return HttpResponseRedirect(reverse('new_url'))

    return render_to_response('current_template.html', locals(), context_instance=RequestContext(request))

Here's my form (fairly simple):

class MyForm(ModelForm):
    first_name = forms.CharField(label='First Name', max_length=50, required=True)
    last_name = forms.CharField(label='Last Name', max_length=50, required=True)
    photo = forms.ImageField(required=False)

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)

    class Meta:
        model = MyModel
        fields = ('first_name','last_name', 'photo')

Here's my model (again very simple):

class MyModel(models.Model):
    first_name = models.TextField(max_length=50)
    last_name = models.TextField(max_length=50)
    photo = ImageField(upload_to=get_photo_path,null=True,blank=True)

Solution

  • This is how I made it work. Notice that there's no 'request.FILES' as a parameter for the constructor of the form in the 'else' when the form is not valid. This is what made Django display the error message.

    if form.is_valid():
        instance = form.save(commit=False)
    
        if request.FILES and request.FILES['photo']:
            instance = save_photo(instance, request.FILES['photo'])
    
        instance.save()
        return HttpResponseRedirect(reverse('url'))
    else:
        if request.FILES and request.FILES['photo']:
            instance = save_photo(instance, request.FILES['photo'])
            form = InstanceForm(request.POST, instance=instance)