0

I have a model that contains a FileField:

class Foo(models.Model):
    fileobj = models.FileField(upload_to="bar/baz")

I am generating a file, and saving it in /tmp/ as part of the save method. This file then needs to be set as the "fileobj" of the model instance.

Currently, I'm trying this:

with open(
    f"/tmp/{self.number}.pdf", "r"
) as h:
    self.fileobj = File(h)

Unfortunately, this fails with: django.core.exceptions.SuspiciousFileOperation:, because the file exists outside of the django project.

I've tried reading the docs, but they didn't help much. Does django take a file, and upon assigning it as a FileField, move it to the media directory, or do I need to manually put it there myself, before attaching it to the model instance. If the second case, what is the point of "upload_to"?

Henry Woody
  • 14,024
  • 7
  • 39
  • 56
Alex
  • 2,270
  • 3
  • 33
  • 65
  • Check this anwer: https://stackoverflow.com/questions/13619600/how-to-generate-temporary-file-in-django-and-then-destroy – ritlew Mar 27 '19 at 18:57
  • Why are you saving the path to a `/tmp` file in django? It is a special file location on linux so it's 1) unsafe to assume the file will stay there, and 2) not portable to other operating systems – ritlew Mar 27 '19 at 19:00
  • @ritlew Because I'm using jinja2 to render a template into a .tex file, and the using subprocess to call xelatex, which outputs a pdf, this should be immediately saved to /media/ by django, and then deleted. – Alex Mar 27 '19 at 19:11

1 Answers1

1

You can use InMemoryUploadedFile object like this.

        import os
        import io
        with open(path, 'rb') as h:
            f = InMemoryUploadedFile(io.BytesIO(h.read()), 'fileobj',
                                     'name.pdf', 'application/pdf',
                                     os.path.getsize(path), None)
            self.fileobj = f
Nafees Anwar
  • 6,324
  • 2
  • 23
  • 42