从Django中的媒体目录打开数据文件

aus*_*acy 6 python django file-io django-media

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

File b'TEST.CSV' does not exist
Run Code Online (Sandbox Code Playgroud)

我试过这个,但没有成功:

file_upload_dir = os.path.join(settings.MEDIA_ROOT, 'Data_Files')
data_file = open(os.path.join(file_upload_dir, new_file), 'rb')
Run Code Online (Sandbox Code Playgroud)

该变量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')
Run Code Online (Sandbox Code Playgroud)

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

这是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
Run Code Online (Sandbox Code Playgroud)

spe*_*ras 8

通常,您不应该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)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您希望它是模块化的,那么拥有一个自定义存储类是个好主意,如果您的需求发生变化,可以轻松配置和使用您的应用程序.此外,这允许将文件放在外面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()
Run Code Online (Sandbox Code Playgroud)

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

所以现在你的代码变成:

from myapp.storage import uploads_storage
f = uploads_storage.open(new_files, 'r')
Run Code Online (Sandbox Code Playgroud)

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