0

Background: I'm am creating Django app to manage receipts. The user will create a new Receipt, fill out some fields with information on the receipt (i.e. cost, items, date purchased, etc.), and upload a copy of the receipt for storage.

Problem: I want to store the receipt *.pdf files in a folder based on the purchase date the user enters, however, I do not have access to self.date.strftime('%Y %B') until after instantiation.

Example Code:

class Receipt(models.Model):
    date = models.DateField()
    item = models.CharField(max_length=128)
    scan = models.FileField(upload_to='scans/{d}/'.format(d=date.strftime('%Y %B')),
                           max_length=100)

Research:

This SO question needs to do something similar, but for a different reason. The answer that he got, was this it was not possible without overriding the save() method. How would that work with file uploads?

This SO question specifically addresses how to set the parameters of FileField with a function; however, it does not involve using fields from the not-yet-complete model (i.e. Receipt).

What are my work-around options?

Michael Molter
  • 1,296
  • 2
  • 14
  • 37
  • Possible duplicate of [Django FileField with upload\_to determined at runtime](https://stackoverflow.com/questions/1190697/django-filefield-with-upload-to-determined-at-runtime) – Arpit Solanki Jun 22 '17 at 21:18
  • Definitely not a duplicate of that question. My question specifically relates to using a models fields to set its own fields. – Michael Molter Jun 22 '17 at 21:20
  • The above question have a perfect answer for your problem. Make a function which uses your datefield and returns you the absolute path for the file. – Arpit Solanki Jun 22 '17 at 21:20
  • I don't believe so? Would my receipt not have to complete initialization before it is available to other functions? In the question you linked, he is returning information from `instance`, a model that already exists. – Michael Molter Jun 22 '17 at 21:22
  • No it really don't have to be initialise to be available to other functions at least not in this case. Read both questions and answer carefully I am 100% sure that it will work for you. – Arpit Solanki Jun 22 '17 at 21:26
  • Wow. I apologize, that does work! – Michael Molter Jun 22 '17 at 21:38
  • Pleasure here. :) – Arpit Solanki Jun 22 '17 at 21:39

1 Answers1

0

Do you need to change upload_to folder in runtime?

this function get the folder name:

def get_upload_to(instance, filename):
        dest = getattr(instance, 'upload_destination', 'scans')
        date = '/{d}/'.format(d=date.strftime('%Y %B')
        return '/'.join([dest, date])

and in upload field (models.py) call the function above:

file = models.FileField(
            upload_to=get_upload_to,
            null=True,
            blank=False
        )

and in model save after request in your view:

your_model = your_form.save(commit=False)
setattr(your_model, 'upload_destination', 'scans/')
your_model.save()

I hope that help's!

Antoniazzi
  • 1,652
  • 1
  • 10
  • 9