简体   繁体   中英

Django 1.6: How to access static files in view

I've already tried the solution here and it didn't work for me. I'm creating a project based off the Heroku "Getting Started" project for Python.

In views.py , I'd like to be able to access a file in the static/data/ folder. However, most of my attempts I make to create the correct url to the file have failed. The only thing that works is putting the absolute path to the file as it exists on my local file system, which obviously won't work when I deploy my app.

Previous attempts to open the file include:

from django.templatetags.static import static
url = static('data/foobar.csv')
os.path.isfile(url) # False

from django.conf import settings
url = os.path.join(settings.STATIC_URL, 'data/foobar.csv')
os.path.isfile(url) # False

Here is my directory structure:

/appname
  /app
    /templates
    views.py
  /appname
    /static
      /js
      /css
      /data
    settings.py
    urls.py

settings.py:

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

DEBUG = True

TEMPLATE_DEBUG = True

ALLOWED_HOSTS = []

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app'
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'appname.urls'

WSGI_APPLICATION = 'appname.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

DATABASES['default'] =  dj_database_url.config()

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

ALLOWED_HOSTS = ['*']

STATIC_ROOT = 'staticfiles'
STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

Instead of joining the STATIC_ROOT with the filename, use the staticfiles_storage interface instead. This will also work with remote static files like S3/django-storages.

from django.contrib.staticfiles.storage import staticfiles_storage

url = staticfiles_storage.url('data/foobar.csv')

With staticfiles_storage you can also do simple file operations like open, delete, save.

The particular staticfiles storage backend you've configured will provide both a path method and a url method.

from django.contrib.staticfiles.storage import staticfiles_storage
p = staticfiles_storage.path('data/foobar.csv')
content = p.readlines()
# manipulate content

The .url method returns the same value as Django's static built-in

url = static('data/foobar.csv')

When you deploy a Django application to Heroku, or when you manually run manage.py collectstatic task, all the static assets will be copied to your STATIC_ROOT directory. Therefore you should use:

file_path = os.path.join(settings.STATIC_ROOT, 'data/foobar.csv')

STATIC_ROOT = 'staticfiles' is your problem. From the docs , STATIC_ROOT is:

The absolute path to the directory where collectstatic will collect static files for deployment.

Currently, you don't even have a path listed there...

Your static files are not at the same place when you are in "dev" or "prod". In dev, you use the django "runserver" command which will serve your static file with "original" files (eg : myproject/src/appname/static/appname/images/plop.jpeg )

In production mode, you must use the "collectstatic" django command which will copy those original file in a "direct public http access folder" (eg : /static/appname/images/plop.jpeg for an http access)

But original files are still at the same place (myproject/src/appname/static/appname/images/plop.jpeg), so your view can access those original file directly.

If you know in which app the file your are looking for is, it is very simple. If you want to use the "static overwrite" mecanims of Django, have a look to its functions to get the "final" static file (for exemple, is it myproject/python-env/lib/python2.7/site-packages/coolapp/static/coolapp/images/plop.jpeg or myproject/src/myapp/static/coolapp/images/plop.jpeg )

I recommend to read the Django Doc about static finders to better understand how it works : https://docs.djangoproject.com/en/3.1/ref/settings/#std:setting-STATICFILES_FINDERS

PS : "HTTP path" and "python path" are not the same ;)

Just had the same problem. Don't know if this is the best solution.

In settings.py I created two paths for switching between productive and development. I need to uncomment when deploying the site.

#Productive
#STATIC_ROOT = '/home/DimiDev/RESite/static'
#Development
STATIC_ROOT = 'realestate/static'

And in my python file, as already stated in this post.

from django.contrib.staticfiles.storage import staticfiles_storage
file_path = staticfiles_storage.path('realestate/ml/2xgBoosting_max.sav')

My structure for this file:

RESite\realestate\static\realestate\ml\2xgBoosting_max.sav

Let me tell you what I did, I made an app in which I had to read a CSV file.
I made the main project directory with django-startproject command and then made an app.
In the root I made a folder named static and inside that, I placed the CSV file.

Now in my views.py
read_csv('static/file_name')

All other settings were default and this worked for me!

What you are trying to do can be achieved the following way. First as your settings.py file has this base path:

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

You can get files in your static directory this way:

url = os.path.join(settings.BASE_DIR, 'static/data/foobar.csv')
os.path.isfile(url) # True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM