Открытие файла данных из медиа-каталога в Django
У меня есть приложение, которое позволяет пользователям загружать файлы 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
1 ответ
Обычно вы не должны получать доступ к файлам, используя open()
в приложении Django. Вы должны использовать API хранилища. Это позволяет вашему коду хорошо играть с настройками Django и потенциальными сторонними приложениями, которые дополняют этот API. https://docs.djangoproject.com/en/1.7/topics/files/
Так что здесь вы должны делать что-то вроде
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
в хранилище, поддерживаемое базой данных, ваш код с удовольствием его использует.