0

I've a django form for FileField where I can input multiple files. I'm trying to send this list of files from django template to views using ajax. But in my views I'm getting False for form.is_valid. Also, form.errors shows:

file_form.errors <ul class="errorlist"><li>file<ul class="errorlist"><li>This fi
eld is required.</li></ul></li></ul>

I'm sure I'm not passing the data correctly through ajax. Do you have any idea where I'm going wrong?

My template:

<form id="file-form" enctype="multipart/form-data", method="POST">
                {% csrf_token %}
                <div id="id_file">{{ file_form }}</div>
                <br><br>
                <input type="submit" value="Upload files" name="_upload_file"/>
            </form>

<script type="text/javascript">
    $(document).on('submit', '#file-form', function(e)){
    e.preventDefault();
    $.ajax({
    type:'POST',
    url:'/create-post/',
    data:{
    files:$('#id_file').val(),
    csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
    },
    success:function(){

    }
    })
    }
</script>

views.py

def upload_files(request):    # create_to_feed
    if request.method == 'POST':
        if PostMediaModelForm(request.POST, request.FILES):
            file_form = PostMediaModelForm(request.POST, request.FILES)
            print("request.post", request.POST)
            ''' request.post <QueryDict: {'csrfmiddlewaretoken': ['CKsF77Sirdfgb72QG5oic86Wc0rHt
            EIW7WYjw78tB9lDwOz5wwh1msdOymgGi9mh', 'CKsF77Sirdfgb72QG5oic86Wc0rHtEIW7WYjw78tB
            9lDwOz5wwh1msdOymgGi9mh'], 'post_body': ['tests going on'], 'file': ['1.jpg', '2
            .jpg', '3.jpg'], '_upload_file': ['Upload files']}> '''

            print("request.FILES", request.FILES)  # request.FILES <MultiValueDict: {}>
            print("file_form.errors", file_form.errors)  # shows the errors mentioned above
            print("file form", file_form.data)
            ''' file form <QueryDict: {'csrfmiddlewaretoken': ['CKsF77Sirdfgb72QG5oic86Wc0rHtEIW
            7WYjw78tB9lDwOz5wwh1msdOymgGi9mh', 'CKsF77Sirdfgb72QG5oic86Wc0rHtEIW7WYjw78tB9lD
            wOz5wwh1msdOymgGi9mh'], 'post_body': ['tests going on'], 'file': ['1.jpg', '2.jp
            g', '3.jpg'], '_upload_file': ['Upload files']}> '''
            print("files are: ", file_form.data.getlist('file'))  # files are:  ['1.jpg', '2.jpg', '3.jpg']
            print("file_form.is_valid()", file_form.is_valid(), "'_upload_file' in request.POST.data", '_upload_file' in request.POST)
            # file_form.is_valid() False '_upload_file' in request.POST.data True
            if '_upload_file' in request.POST:
                files = request.FILES.getlist('file')
                print("files: ", files)  # files:  []
                print("no. of files: ", len(files))  # no. of files:  0
                for f in files:
                    PostMedia.file = f
                    PostMedia.save(update_fields=["file"])
                messages.success(request, 'File(s) uploaded!')
                # return redirect('submit_post')
                return HttpResponse('')
            # else:
            #     return HttpResponse(str(file_form.errors))
        elif PostModelForm(request.POST):
            form = PostModelForm(request.POST)
            if form.is_valid and '_create_post' in request.POST:
                feed_instance = form.save(commit=False)
                PostMedia.body = feed_instance
                feed_instance.save()
                PostMedia.save(update_fields=["body"])
                messages.success(request, 'Your post was submitted successfully !')
                return redirect('/create-post')

    else:
        form = PostModelForm()
        file_form = PostMediaModelForm()
        return render(request, 'multiuploads/form.html', {'form': form, 'file_form': file_form})

models.py

class Post(models.Model):  
    post_body = models.TextField(blank=False, max_length=500)   

    def __str__(self):
        return str(self.post_body)


class PostMedia(models.Model):  
    file = models.FileField(blank=False, null=False, validators=[FileExtensionValidator(['jpg'])])
    body = models.ForeignKey(Post, on_delete=models.CASCADE)

forms.py


class PostModelForm(ModelForm):
    class Meta:
        model = Post
        fields = ['post_body']


class PostMediaModelForm(ModelForm):
    class Meta:
        model = PostMedia
        fields = ['file']
        widgets = {
            'file': ClearableFileInput(attrs={'multiple': True}),
        }

This is the my front end: As you can see after clicking the upload button I should be able to save the form as in upload the files in the background while still staying on the same page and the once the I see file uploaded message I can be able to submit the whole form.

As you can see after clicking the upload button I should be able to save the form as in upload the files in the background while still staying on the same page and the once the I see file uploaded message I can be able to submit the whole form. Thanks in advance!

user10058776
  • 183
  • 1
  • 3
  • 17
  • 2
    Have you checked the answers in: https://stackoverflow.com/questions/2320069/jquery-ajax-file-upload ? – schillingt Jan 18 '19 at 19:46
  • @schillingt I don't want to upload file through ajax, I want to POST the list of input files and file uploading will be done in the django views. I tried to pass them in the data attribute of ajax.I've attached the code, will you please check out and tell me the correct code? – user10058776 Jan 19 '19 at 07:26
  • @ThomasJiang can you answer this? – user10058776 Jan 19 '19 at 09:50
  • You're making an ajax call to submit the form but you don't want to upload the file through ajax? Can you elaborate what you're trying to do? Your form is expecting to receive files (including the file data) so what do you mean by "file uploading will be done in the django view?" And maybe show us your `CreatePost` view to see how you handle the ajax post. – dirkgroten Jan 21 '19 at 10:04
  • @dirkgroten I've given everything now in the edited question. I don't know anything about ajax, but this task required me to use it. I believe I've to send(post) the form data through ajax to django views where my form will be saved(files will be saved) – user10058776 Jan 22 '19 at 07:31
  • As you can see, request.FILES is empty, meaning your ajax call isn't submitting the files. You say you don't know anything about ajax but you dismissed @schillingt's comment, which was the correct answer. You should do what's in the link. – dirkgroten Jan 22 '19 at 09:15
  • Yes I checked the answers he wanted me to..but this one is a different use case, else I wouldn't have asked the question. @dirkgroten And I'd figured out that ajax is not submitting the files, that's what I've asked how can submit those files as they're gonna be a list of files. – user10058776 Jan 22 '19 at 13:53
  • It's not a different use case! It's about how to upload a file using an ajax (xhr) request. Use a FormData object as described in the answers to add the files to your post request. – dirkgroten Jan 22 '19 at 13:55
  • @dirkgroten I actually had tried that, but it didn't work. Can you write the code? – user10058776 Jan 22 '19 at 14:01
  • https://stackoverflow.com/a/36257330/1252711 (I just searched "multiple files upload ajax formdata"). – dirkgroten Jan 22 '19 at 14:02
  • Hi, I tried with every single solution over there but still see "Form contains a file input, but is missing method=POST and enctype=multipart/form-data on the form. The file will not be sent." in the console. I do have these things in my form. @dirkgroten – user10058776 Jan 22 '19 at 14:53
  • that's when you click 'upload files' button or the 'create post' button? I'm assuming we're talking about the 'upload files' button at the moment, since that's the one that should post the files. – dirkgroten Jan 22 '19 at 14:59
  • @dirkgroten yes..and this error has been from the first – user10058776 Jan 22 '19 at 15:07
  • sounds like your script isn't even running since that's an error you'd see on normal HTML form submission, not on the `ajax()` call. Check with breakpoints that your script is actually running (stop on the $.ajax()) line. Also make sure you add all options mentioned in the post I linked (contentType and processData. And since you're not showing your javascript code (the one in the question isn't what has been suggested) it's hard to help. – dirkgroten Jan 22 '19 at 15:15

0 Answers0