167

I'm using reportlab pdfgen to create a PDF. In the PDF there is an image created by drawImage. For this I either need the URL to an image or the path to an image in the view. I managed to build the URL but how would I get the local path to the image?

How I get the URL:

prefix = 'https://' if request.is_secure() else 'http://'
image_url = prefix + request.get_host() + STATIC_URL + "images/logo_80.png"
ppython
  • 485
  • 6
  • 19
olofom
  • 6,233
  • 11
  • 37
  • 50

8 Answers8

335
# Older Django <3.0 (also deprecated in 2.0):
from django.contrib.staticfiles.templatetags.staticfiles import static

# Django 3.0+
from django.templatetags.static import static

url = static('x.jpg')

url now contains '/static/x.jpg', assuming a static path of '/static/'

xyres
  • 20,487
  • 3
  • 56
  • 85
dyve
  • 5,893
  • 2
  • 30
  • 44
  • 2
    Do you know if there's a clean way of adding the hostname to the static url (if not present in STATIC_URL)? I need to add images or other resources in mails, where the user won't be able to find the resources with relative urls. – gepatino Sep 12 '13 at 20:00
  • 5
    This does not work for me while running in Debug (haven't tried yet with DEBUG=False). I simply get the path passed into the static method returned. Using Django 1.6. Any thoughts? – Shawn Dec 12 '13 at 16:40
  • I think the code using django.contrib.staticfiles.templatetags.staticfiles should be prefered taking into account that is compatible with django-storages and similar. – jdcaballerov Jul 10 '14 at 18:30
  • @gepatino You can route the result through `request.build_absolute_uri` as described here: http://stackoverflow.com/questions/2345708/how-can-i-get-the-full-absolute-url-with-domain-in-django – dyve Nov 11 '14 at 13:44
  • 1
    For anyone having the same problem as @Shawn (or me), this could be because you are giving a path that starts with a slash. Don't do `static('/style.css')`, do instead `static('style.css')`. – Djizeus Oct 05 '15 at 21:08
  • 32
    In Django 2.0, this will show a deprecation notice. Use `from django.templatetags.static import static` instead. – Flimm May 11 '17 at 10:21
  • In Django 2.0.1 server logs, I am getting a `No such file or directory: '/static/my_file_name.xlsx'` whereas I can see the file if I access the URL directly from the browser `localhost:8080/static/my_file_name.xlsx` – Anupam Jan 25 '18 at 08:56
  • 1
    @Anupam you probably added `'/static'` to your argument to the `static` function, which isn't right. Try `static('my_file_name.xlsx')`. – shad0w_wa1k3r Mar 20 '18 at 09:02
  • I get **[Errno 30] Read-only file system: '/static'** – AnonymousUser Feb 12 '22 at 05:14
  • I got this error when I tried to use it inside settings.py: django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. – Karam Qusai Nov 23 '22 at 10:40
94

EDIT: If you're on Django >=3.0, refer to Django get the static files URL in view instead. This was answered with Django 1.X version.

dyve's answer is good one, however, if you're using "cached storage" on your django project and final url paths of the static files should get "hashed"(such as style.aaddd9d8d8d7.css from style.css), then you can't get a precise url with django.templatetags.static.static(). Instead, you must use template tag from django.contrib.staticfiles to get hashed url.

Additionally, in case of using development server, this template tag method returns non-hashed url, so you can use this code regardless of that the host it is development or production! :)

from django.contrib.staticfiles.templatetags.staticfiles import static

# 'css/style.css' file should exist in static path. otherwise, error will occur 
url = static('css/style.css')
Kenial
  • 2,510
  • 23
  • 26
  • 1
    Thanks for this... took me a while to figure out why I wasn't getting my md5 hashes injected – ilovett May 25 '14 at 02:29
  • 4
    This answer is still getting hits and is actively used, so I improved my accepted answer with credits to @Kenial. This is still the preferred solution for this problem. – dyve Oct 07 '15 at 05:24
  • 1
    In Django 3.2, there is no templatetags in django.contrib.staticfiles. See https://stackoverflow.com/a/59355195 – dfrankow Nov 10 '21 at 00:09
  • @dfrankow seemed I made this answer in the somewhere of Django 1.3... wow it has been a while. Thanks for enhancing it up! – Kenial Nov 10 '21 at 19:03
35

From Django 3.0 you should use from django.templatetags.static import static:

from django.templatetags.static import static

...

img_url = static('images/logo_80.png')
devaerial
  • 2,069
  • 3
  • 19
  • 33
15

here's another way! (tested on Django 1.6)

from django.contrib.staticfiles.storage import staticfiles_storage
staticfiles_storage.url(path)
David Lam
  • 4,689
  • 3
  • 23
  • 34
  • Good solution as this will return the hashed URL if DEBUG is set to False. Optionally force the hashed URL like so: `staticfiles_storage.url(path, force=True)` – Marc Gibbons May 30 '19 at 16:34
11

Use the default static tag:

from django.templatetags.static import static
static('favicon.ico')

There is another tag in django.contrib.staticfiles.templatetags.staticfiles (as in the accepted answer), but it is deprecated in Django 2.0+.

Max Malysh
  • 29,384
  • 19
  • 111
  • 115
8

@dyve's answer didn't work for me in the development server. Instead I solved it with find. Here is the function:

from django.conf import settings
from django.contrib.staticfiles.finders import find
from django.templatetags.static import static

def get_static(path):
    if settings.DEBUG:
        return find(path)
    else:
        return static(path)
Jahongir Rahmonov
  • 13,083
  • 10
  • 47
  • 91
6

If you want to get absolute url(including protocol,host and port), you can use request.build_absolute_uri function shown as below:

from django.contrib.staticfiles.storage import staticfiles_storage
self.request.build_absolute_uri(staticfiles_storage.url('my-static-image.png'))
# 'http://localhost:8000/static/my-static-image.png'
Mesut Tasci
  • 2,970
  • 1
  • 30
  • 36
0

In short words you need to get

  • STATIC_URL
  • STATIC_ROOT
  • urlpatterns
  • staticfiles
  • templatetags
  • url parameters

All in the right place, to get this working. In addition, in real time deployment, circumstances vary, which it is very possible that the current setting you spent 3 hours worked out, works on your local machine but the server.

So I adopted the traditional way!!

app
├── static
│   └── json
│       └── data.json
└── views.py

views.py

import os

with open(os.path.abspath(os.getcwd()) + '/app/static/json/data.json', 'r') as f:
    pass
Weilory
  • 2,621
  • 19
  • 35