Как загружать изображения при помощи CreateView с динамическим upload_to у поля ImageField/FileField?

У меня есть модель Book с полем image, в которое сохраняется обложка книги. В качестве параметра upload_to у этого поля я указал функцию image_directory_path, которая создает динамический путь к обложке по следующему образцу: media/catalog/book_covers/book_{id книги} и сохраняет обложку по этому пути.

При добавлении книги через стандартную админ-панель Django все работает как задумано, однако, если добавлять книгу через форму, то обложки почему-то добавляются в media/catalog/book_covers/book_None.

Почему так получается и что с этим делать?

Код функции image_directory_path:

def image_directory_path(instance, filename):
    return f'catalog/book_covers/book_{instance.id}/{filename}'

Код модели Book:

class Book(models.Model):
    image = models.ImageField(upload_to=image_directory_path,
                              default='catalog/book_covers/default_image.png',
                              verbose_name='Обложка')

forms.py:

class AddBookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ['image']

views.py:

class BookCreateView(CreateView):
    model = Book
    form_class = AddBookForm
    template_name = 'catalog/add_book.html'
    extra_context = {'page_title': 'Добавление книги'}

    def get_success_url(self):
        return self.object.get_absolute_url()

add_book.html:

<form action="{% url 'add_book' %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}

    {% for f in form %}
        <label for="{{ f.id_for_label }}">{{ f.label }}</label>
        <p>{{ f }}</p>
    {% endfor %}

    <button type="submit">Подтвердить</button>
</form>

UPD: Я прислушался к комментарию @andreymal и реализовал сохранение при помощи вот такой функции-представления:

image = form.cleaned_data['image'] # Если пользователь не прикрепил картинку, то берется 
# картинка по умолчанию, благодаря свойству default поля image

if 'image' in request.FILES:
    image = request.FILES['image']

# Создаем экземпляр класса Book без поля image
new_book = Book(title=title,
                author=author,
                description=description,
                genre=genre,
                year=year)

new_book.save() # После Сохранения у книги в БД появляется id
new_book.image = image # Изменяем поле image у сохраненной книги
new_book.save() # Сохраняем изменения

Теперь сохранение работает корректно, однако остается открытым вопрос: как загружать изображения при помощи CreateView с динамическим upload_to у поля ImageField/FileField?


Ответы (0 шт):