Dean
Dean

Reputation: 1236

How do I override django admin's default file upload behavior?

I need to change default file upload behavior in django and the documentation on the django site is rather confusing.

I have a model with a field as follows:

class document (models.Model):
    name = models.CharField(max_length=200)
    file = models.FileField(null=True, upload_to='uploads/')

I need to create a .json file that will contain meta data when a file is uploaded. For example if I upload a file mydocument.docx I need to create mydocument.json file within the uploads/ folder and add meta information about the document.

From what I can decipher from the documentation I need to create a file upload handler as a subclass of django.core.files.uploadhandler.FileUploadHandler. It also goes on to say I can define this anywhere I want.

My questions: Where is the best place to define my subclass? Also from the documentation found here https://docs.djangoproject.com/en/1.8/ref/files/uploads/#writing-custom-upload-handlers looks like the subclass would look like the following:

class FileUploadHandler(object):
    def handle_raw_input(self, input_data, META, content_length, boundary, encoding=None):
        # do the acctual writing to disk        
    def file_complete(self, file_size):
        # some logic to create json file

Does anyone have a working example of a upload handler class that works for django version 1.8?

Upvotes: 1

Views: 1281

Answers (1)

James Hiew
James Hiew

Reputation: 7117

One option could be to do the .json file generation on the (model) form used to initially upload the file. Override the save() method of the ModelForm to generate the file immediately after the model has been saved.

class DocumentForm(forms.ModelForm):
    class Meta(object):
        model = Document
        fields = 'name', 'file'

    def save(self, commit=True):
        saved_document = super().save(commit)
        with open(saved_document.file.path + '.json', mode='w') as fh:
            fh.write(json.dumps({
                "size": saved_document.file.size,
                "uploaded": timezone.now().isoformat()
            }))
        return saved_document

I've tested this locally but YMMV if you are using custom storages for working with things like S3.

Upvotes: 1

Related Questions