9

我有一个应用程序,允许用户上传带有数据的 CSV 文件,然后将这些数据绘制成图形并显示给用户。这些文件作为媒体保存在我的媒体文件夹中。但是,在我的图表视图中,我需要打开文件并处理它。我的问题是我只能打开项目当前工作目录中的文件,并且每当我尝试从该目录之外的某个位置上传文件时,我都会收到此错误:

File b'TEST.CSV' does not exist

我已经尝试过了,但没有成功:

file_upload_dir = os.path.join(settings.MEDIA_ROOT, 'Data_Files')
data_file = open(os.path.join(file_upload_dir, new_file), 'rb')

该变量new_file只是会话中保存的文件的名称,而不是该文件的路径。Data_Files是媒体目录中包含上传文件的目录。

我的 Django 媒体设置是

SETTINGS_DIR = os.path.dirname(__file__)
PROJECT_PATH = os.path.join(SETTINGS_DIR, os.pardir)
PROJECT_PATH = os.path.abspath(PROJECT_PATH)

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media')

有没有办法从视图中正确引用媒体文件?

这是新文件的输出file_upload_dir和位置。

>>> print(file_upload_dir)
C:\\Users\\vut46744\\Desktop\\graphite_project\\media\\Data_Files

>>> print(os.path.join(file_upload_dir, new_file))
C:\\Users\\vut46744\\Desktop\\graphite_project\\media\\Data_Files\\TEST.CSV
4

1 回答 1

12

通常,您不应使用open()Django 应用程序访问文件。您应该使用存储 API。这使您的代码可以很好地与 Django 设置以及增强此 API 的潜在第三方应用程序配合使用。 https://docs.djangoproject.com/en/1.7/topics/files/#file-storage

所以在这里你应该做类似的事情

from django.core.files.storage import default_storage

f = default_storage.open(os.path.join('Data_Files', new_file), 'r')
data = f.read()
f.close()
print(data)

顺便说一句,如果您希望它是模块化的,最好有一个自定义存储类,以便在您的需求发生变化时轻松配置和使用您的应用程序。此外,这允许将文件放在MEDIA_ROOT. 此示例存储会将它们放入(如果未找到设置,则settings.UPLOADS_ROOT默认为)。MEDIA_ROOT

# Put this in a storage.py files in your app
from django.conf import settings
from django.core.files.storage import FileSystemStorage, get_storage_class
from django.utils.functional import LazyObject

class UploadsStorage(FileSystemStorage):
    def __init__(self, location=None, base_url=None, *args, **kwargs):
        if location is None:
            location = getattr(settings, 'UPLOADS_ROOT', None)
        super(UploadsStorage, self).__init__(location, base_url, *args, **kwargs)
        self.base_url = None  # forbid any URL generation for uploads

class ConfiguredStorage(LazyObject):
    def _setup(self):
        storage = getattr(settings, 'UPLOADS_STORAGE', None)
        klass = UploadsStorage if storage is None else get_storage_class(storage)
        self._wrapped = klass()
uploads_storage = ConfiguredStorage()

我们在这里创建一个非常简单的存储。它只是普通的,但它从另一个目录读取它的文件。然后我们设置一个惰性对象,允许从设置中覆盖该存储。

所以现在你的代码变成了:

from myapp.storage import uploads_storage
f = uploads_storage.open(new_files, 'r')

在您的设置中,您UPLOADS_ROOT可以随意设置。可能是您的媒体目录之外的内容。如果有一天你决定将上传的内容存储在数据库中,你可以设置UPLOADS_STORAGE为数据库支持的存储,你的代码会很乐意使用它。

于 2014-12-21T04:25:10.870 回答