0

My app has a simple process, the user uploads a gif file and then the gif is conveted to frames that are saved as objects. For the upload_to part of my gif, I run a function content_file_name() that uses uuid to create a folder path. I want the image frames to be saved to the same folder as the gif. Problem is, I can't set the path as a variable as much as I try. The variable needs to be defined first, but if I define it, it doesn't change no matter what I do. Here's what I got now:

currentFilePath = '' # Defining the variable 

def content_file_name(instance, filename):
    ext = ''.join(filename.split())[:-4]
    foldername = "%s/%s" % (uuid.uuid4(), ext)
    store_random_path('/'.join(['documents', str(foldername)])) # Running a function to change the variable
    return '/'.join(['documents', str(foldername), filename])

def store_random_path(path):
    currentFilePath = str(path) # The variable should be changed here

class Document(models.Model):
docfile = models.ImageField(upload_to=content_file_name)
def create_documentfiles(self):
    gif = Image.open(self.docfile.path)
    frames = [frame.copy() for frame in ImageSequence.Iterator(gif)]
    basename, _ext = os.path.splitext(self.docfile.name)
    for index, frame in enumerate(frames):
        buffer = BytesIO()
        frame.convert('RGB').save(fp=buffer, format='JPEG')
        destname = "{}{}.png".format(basename, index)
        finalImage = InMemoryUploadedFile(buffer, None, destname, 'image/jpeg', frame.tell, None)
        imageToSave = DocumentImage(imagefile=finalImage)
        imageToSave.save()

class DocumentImage(models.Model):
    imagefile = models.ImageField(upload_to=currentFilePath) # Trying to save using the variable as path
    image = models.ForeignKey(Document, related_name='Image', null=True, on_delete=models.CASCADE)

So, when the DocumentImage gets saved, it should have seen the variable as path, but it doesn't. Instead it just saves to the initially declared '' which is the root of my media file. Not sure if what I'm trying is possible in Python/Django. I've just started learing Python a month ago. Thank you for your time.

2 Answers2

0

But all you've done is to set a local variable inside store_random_path. You haven't even returned that variable, let alone changed the global variable with the same name.

But you must not use global variables like this anyway. That would cause serious bugs as any future request would get the same value of the global variable. Don't do this.

I'm not sure why you are trying to set this variable in the first place. You have access to the Document, which contains the docfile which has its path correctly set. You should use that to calculate the path of the frames.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Can you explain how to set upload_to as the docfile.path in my current example? I would like to avoid a global variable if possible, but I'm not accustomed to Python and Django, so I don't understand how to us the constructor. – Revolvelot McShooty Jun 21 '17 at 08:32
0

You are assigning to a global variable inside a function. You need to use the global keyword for that or you could refactor your code to not use any global variable (see Why are global variables evil?). This is not specific to Django.

The wrong way

global_var = ''

def function():
    global_var = 'hello' # Local variable created due to assignment

Here global_var is still ''

The Correct way

global_var = ''

def function():
    global global_var
    global_var = "hello" # Assignment to the global variable

Here global_var is "Hello"

Priyam Singh
  • 816
  • 2
  • 11
  • 10
  • You shouldn't encourage people to use global variables. This is bad in most circumstances, but especially bad in an environment like Django where one process will serve request for multiple users. – Daniel Roseman Jun 21 '17 at 08:27