Search code examples
djangoformsfile-uploadpytube

Validate django form with local files


My web page has the option of upload videos using a form, but I wanted to extend its functionalities adding the option of giving a YouTube URL instead of uploading a file.

With the file upload there is no problem, as I validate the form from a model:

forms.py

class VideoForm(forms.ModelForm):
    class Meta:
        model = Video
        fields = ('file', 'description', 'url')

models.py

class Video(models.Model):
    file = models.FileField(upload_to=video_directory_path)
    description = models.TextField(blank=True)
    url = models.CharField(max_length=255, blank=True)

and everything works fine, but when I try to do that sending the video's URL, the form = VideoForm(request.POST, request.FILES) won't work by itself as request.FILES is empty, but I tried many things like:

form = VideoForm(request.POST,
                 MultiValueDict({'file': [open(fname,'r')]}))

and VideoForm always returns:

<tr><th><label for="id_file">File:</label></th><td><ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul><input type="file" name="file" required id="id_file" /></td></tr>
<tr><th><label for="id_description">Description:</label></th><td><textarea name="description" rows="10" cols="40" id="id_description">
</textarea></td></tr>
<tr><th><label for="id_url">Url:</label></th><td><input type="text" name="url" value="https://www.youtube.com/watch?v=kj7wTDK5Vx8" id="id_url" maxlength="255" /></td></tr>

The question is, there is a way to set request.FILES with a local file for validating a form? I use the pytube library in order to download a video, and it works fine because it displays a bit stream when I do open(fname,'r').read(), and open(fname,'r') returns {'file': <open file u'markst.mp4', mode 'r' at 0x7f375b654db0>}

I hope my issue is clear, and thanks in advance!


Solution

  • I managed to solve it using the Django's File object in the following way:

    from django.core.files import File
    from django.utils.datastructures import MultiValueDict
    
    file = open(fname, 'r') # Reads the downloaded video
    fileform = File(file)
    form = VideoForm(data=request.POST, files=MultiValueDict({'file': [fileform]}))
    

    With this, the form object finally passes the validation when doing form.is_valid().

    I hope this helps someone with the same problem I had.