Не знаю как вы, а я чаще стал сталкиваться с ситуацией, когда мне нужно программно загрузить файл из локальной файловой системы или с помощью удаленного URL в модель Django. Это может понадобиться в контексте работы в оболочке Python, исполнения отдельного скрипта или команды управления Django.
В типичном веб-приложении такая задача встречается нечасто. Я заметил, что мы это делаем, когда переносим сайт с какой-то другой технологии на Django, и привязываем изображение к некой контентной сущности.
Если вы поищете ответ как сделать это в Google, то обнаружите документацию Django File Uploads, File objects и Managing Files, которые сами по себе отличные. Тем не менее они не содержат последовательного руководства для решения нашей задачи.
Первый порыв — присвоить полю модели путь к файлу, но это ведет к потере информации об относительном пути к файлу, в которой нуждается Django.
Я выделил время, чтобы написать этот пост в основном для собственного блага, чтобы не искать заново решение в будущем. Но, надеюсь, вы также получите некоторую пользу.
Этапы загрузки локального файла в Django ImageField
Действия, которые необходимо выполнить:
- Получить файл (если он удаленный) и сохранить его локально
- Открыть файл как обычный объект файла Python
- Конвертировать открытый файл в Django FIle
- Привязать его к полю вашей модели
Пример модели
Предположим, у нас есть модель вроде этой:
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=100)
logo = models.ImageField()
Давайте создадим запись для RevSys, скачав логотип с помощью библиотеки requests:
import requests
from django.core.files import File
from .models import Company
r = requests.get(“http://media.revsys.com/img/revsys-logo.png”)
with open(“/tmp/revsys-logo.png”, “wb”) as f:
f.write(r.content)
reopen = open(“/tmp/revsys-logo.png”, “rb”)
django_file = File(reopen)
revsys = Company()
revsys.name = “Revolution Systems”
revsys.logo.save(“revsys-logo.png”, django_file, save=True)
Последняя строка здесь самая важная. Методу save передается три аргумента:
- Относительный путь и имя файла внутри MEDIA_ROOT.
- Файл, открытый с помощью File объекта Django.
- Логическое значение, показывающее хотим ли мы сохранить экземпляр revsys модели Company после того, как изображение сохранено.
Иногда, если вы работаете с набором изображений, вам требуется распарсить URL или пути к файлам для извлечения имен файлов. Нижеследующий код послужит отправной точкой. Обратите внимание, что тут используется Python 3:
import os
from urllib.parse import urlparse
# from urlparse import urlparse for Python 2.7
url = “http://media.revsys.com/img/revsys-logo.png”
filename = os.path.basename(urlparse(url).path)
# This returns ‘revsys-logo.png’ from the URL
…
revsys.logo.save(filename, django_file, save=True)`
Надеюсь, это вам поможет!
Эта статья перевод. Оригинал: Loading Django FileField and ImageFields from the file system