Django 1.6:如何在视图中访问静态文件

17

我已经尝试了这里的解决方案,但对我无效。我正在创建一个基于Heroku Python“入门”项目的项目。

views.py中,我想能够访问static/data/文件夹中的文件。然而,我尝试创建正确的文件url的大部分尝试都失败了。唯一有效的方法是将文件在本地文件系统上的绝对路径放入代码中,但这显然不能在部署应用程序时使用。

以前尝试打开文件的方式包括:

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

这是我的目录结构:

/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'),
)

尝试使用“/static/data/foobar.csv”。 - jatinkumar patel
8个回答

19

不要将STATIC_ROOT和文件名拼接在一起,改用staticfiles_storage接口。这也适用于远程静态文件,如S3 / django-storages。

from django.contrib.staticfiles.storage import staticfiles_storage

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

通过staticfiles_storage,您还可以执行诸如打开、删除、保存等简单文件操作。


2
对我来说,这指向了/static/...并且在开发和生产环境中都出现了问题。在开发环境中,如果我使用没有前导斜杠的static/...,它可以正常工作。在生产环境(Heroku)中,静态文件被复制到STATIC_ROOT = staticfiles下,并且在static/...下找不到任何内容。 - CGFoX

14

你配置的特定的静态文件存储后端将提供一个path方法和一个url方法。

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

.url 方法返回与 Django 的静态内置方法相同的值。

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

7
当你将Django应用程序部署到Heroku上,或手动运行manage.py collectstatic任务时,所有静态资源将被复制到STATIC_ROOT目录中。因此,你应该使用:
file_path = os.path.join(settings.STATIC_ROOT, 'data/foobar.csv')

5
您的问题在于:STATIC_ROOT = 'staticfiles'。从文档中可以看出,STATIC_ROOT是:

绝对路径,用于存储集合静态文件以便部署的目录。

当前您甚至没有在那里列出路径...


3

您的静态文件在“dev”或“prod”中不在同一位置。

在dev中,您使用django的“runserver”命令,该命令将使用“原始”文件(例如:myproject/src/appname/static/appname/images/plop.jpeg)来提供静态文件。

在生产模式下,您必须使用“collectstatic”django命令,该命令会将这些原始文件复制到“直接公共http访问文件夹”中(例如:/static/appname/images/plop.jpeg以进行http访问)。

但原始文件仍然位于同一位置(myproject/src/appname/static/appname/images/plop.jpeg),因此您的视图可以直接访问这些原始文件。

如果您知道要查找的文件位于哪个应用程序中,则很简单。如果您想要使用Django的“静态覆盖”机制,请查看其函数以获取“final”静态文件(例如,它是myproject/python-env/lib/python2.7/site-packages/coolapp/static/coolapp/images/plop.jpeg还是myproject/src/myapp/static/coolapp/images/plop.jpeg

我建议阅读Django文档以更好地理解静态查找器的工作原理:https://docs.djangoproject.com/en/3.1/ref/settings/#std:setting-STATICFILES_FINDERS

PS:“HTTP路径”和“Python路径”不同;)


1
让我告诉你我做了什么,我制作了一个应用程序,其中我必须读取CSV文件。 我使用django-startproject命令创建了主项目目录,然后创建了一个应用程序。 在根目录下,我创建了一个名为static的文件夹,并将CSV文件放在其中。
现在在我的views.py中, read_csv('static/file_name') 所有其他设置都是默认的,这对我起作用了!

1

我遇到了同样的问题。不知道这是否是最佳解决方案。

在settings.py中,我创建了两个路径以在生产和开发之间切换。在部署网站时,我需要取消注释。

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

在我的Python文件中,就像这篇文章中已经说明的那样。
from django.contrib.staticfiles.storage import staticfiles_storage
file_path = staticfiles_storage.path('realestate/ml/2xgBoosting_max.sav')

这个文件的结构:

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

path 对于我的用例比其他回答中使用的 url 更合适。 - caram

0
你想要做的事情可以通过以下方式实现。 首先,由于你的settings.py文件具有这个基本路径:
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

您可以通过以下方式获取静态目录中的文件:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接