0

I'm trying to learn django, and this has me at the end of my rope. I'm using requests to try and post a user-uploaded image file to an external site, following this example. For testing purposes, I'm using request bin for the url so I can see what's being posted.

When I hardcode a filepath and name into files to test, the whole thing works great. My problem is I don't understand what to do to handle the real-world use case, where I don't know what the user's named the file, and the path will change based on date/month/year.

Every post I've seen on this, as well as the requests example, looks like this:

>>> files = {'file': open('report.xls', 'rb')}

models.py

def get_image_path(instance, filename):
    return '/'.join(['help_screens/%Y/%m/%d', filename])

class Help(Timestamp):
First_name = models.CharField(max_length=30)
Last_name = models.CharField(max_length=40)
email = models.EmailField()
themessage = models.TextField()
screenshot = models.ImageField(
    upload_to=get_image_path,
    null=True,
    blank=True
)

views.py

def help_form(request):
    form = HelpForm()

    if request.method == 'POST':
        form = HelpForm( request.POST, request.FILES )

        if form.is_valid():
            First_name = form.cleaned_data['First_name']
            Last_name = form.cleaned_data['Last_name']
            email = form.cleaned_data['email']
            themessage = form.cleaned_data['themessage']
            screenshot = form.cleaned_data['screenshot']

            # Email the help request
            template = get_template('help_template.txt')

            context = Context({
                 'First_name': First_name,
                 'Last_name': Last_name,
                 'email': email,
                 'themessage': themessage,
                 'screenshot': screenshot,
             })
             content = template.render(context)

             mail = EmailMessage(
                 'New help request',
                 content,
                 'test website <test@test.com>',
                 ['my.test@mytest.com', email],
                 headers = {'Reply-To': email }
            )
            if screenshot:
                mail.attach(screenshot.name, screenshot.read())
            mail.send()
            # End email the help request

            form = form.save(commit=False)

            url = 'http://requestb.in/xxxxxx'
            payload = {
                'First_name': First_name,
                'Last_name': Last_name,
                'email': email,
                'themessage': themessage,
            }
            if screenshot != None:
            # this works, but it's a test to a hard-coded file. the           
            # problem remains, how to get the filepath and file.
            # files = {'screenshot': open('test/media-root/help_screens/boots.jpg', 'rb')}
            files = {'screenshot': open('screenshot.jpg', 'rb')}
            req = requests.post(url, data=payload, files=files)
        else:
            req = requests.post(url, data=payload)
            req.text
            form.save()

            return render(request, 'help/thanks.html')

    return render(request, 'help/help.html', {
        'form': form,
    })
ed sherry
  • 33
  • 1
  • 5
  • What's your `get_image_path`? Is it set to `test/media-root/help_screens` and are you sure you're in the same relative path to `test` as when running the server? You should consider using an absolute path, eg `/tmp/test/...`. – olofom Feb 29 '16 at 23:04
  • My get_image_path looks like this: `def get_image_path(instance, filename): return '/'.join(['help_screens/%Y/%m/%d', filename])`. I guess it picks up the project name and media-root from the media_root in settings. Are you saying I can use get_image_path in the files portion of the requests.post? – ed sherry Mar 01 '16 at 00:30
  • `upload_to` will prefix with `MEDIA_ROOT` (see https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.FileField.upload_to), but open won't automatically use it. Is your `MEDIA_ROOT` `test/media-root/`? And is that path available relative to where the file is loaded? – olofom Mar 01 '16 at 21:08
  • My MEDIA_ROOT is os.path.join(BASE_DIR, 'test/media-root/'), and I believe that path is available relative to where the file is loaded. For example, I can send myself an email with the all fields from the form, including the image file (I just updated my views.py with those lines). – ed sherry Mar 01 '16 at 21:20
  • What if you imported `MEDIA_ROOT` and used it in your `open`? `open(os.path.join(MEDIA_ROOT, 'help_screens/boots.jpg'), 'rb')` – olofom Mar 01 '16 at 22:15
  • I see what you're saying. But my question is, how do I know the name of the file the user uploaded? I can't hardcode "boots.jpg". And if I use "help_screens/%Y/%m/%d" to better organize the files by year/month/date in the media root folder, how do I get to that path? I feel like I'm missing something really basic here (and I appreciate you taking the time to help me with this!). – ed sherry Mar 02 '16 at 15:50
  • Ah, I understand. I'll write it as an answer to be able to elaborate better. – olofom Mar 02 '16 at 20:48

1 Answers1

0

For example, say your MEDIA_ROOT is set to '/home/media', and upload_to is set to 'photos/%Y/%m/%d'. The '%Y/%m/%d' part of upload_to is strftime() formatting; '%Y' is the four-digit year, '%m' is the two-digit month and '%d' is the two-digit day. If you upload a file on Jan. 15, 2007, it will be saved in the directory /home/media/photos/2007/01/15.

If you wanted to retrieve the uploaded file’s on-disk filename, or the file’s size, you could use the name and size attributes respectively; for more information on the available attributes and methods, see the File class reference and the Managing files topic guide.

Source: https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.FileField.storage

And here are some examples as well: https://docs.djangoproject.com/en/1.9/topics/files/

So to get the name of screenshot, you'd do screenshot.name and respectively screenshot.path to get the full path.

olofom
  • 6,233
  • 11
  • 37
  • 50
  • I can't thank you enough. Your help and a little more reading which led me to [this answer](http://stackoverflow.com/questions/3702465/how-to-copy-inmemoryuploadedfile-object-to-disk) solved my problem. Thank you! – ed sherry Mar 03 '16 at 20:42