Не удается динамически создать путь с upload_to - PullRequest
0 голосов
/ 23 июня 2019

В моей пользовательской модели у меня есть ImageField, который содержит атрибут upload_to, который будет динамически создавать путь к изображению на основе идентификатора пользователя.

avatar  = models.ImageField(storage=OverwriteStorage(), upload_to=create_user_image_path)

def create_user_image_path(instance, image_name):
    image_name = str(instance.user.id) + image_name[-4:]
    return 'users/{0}/avatars/{1}'.format(instance.user.id, image_name)

Когда я регистрируюсь, я получаюошибка, которая выглядит следующим образом:

Системе не удается найти указанный путь: 'C: \ Users \ xx \ PycharmProjects \ имя_проекта \ media \ users \ 150 \ avatars'

Если я удаляю id и аватары и просто включаю имя изображения (без новых каталогов), оно успешно работает и записывает изображение.Я попытался сделать chmod -R 777 для этого каталога, но он по-прежнему не создает эти новые каталоги динамически.Я не уверен, что делаю не так.

РЕДАКТИРОВАТЬ

class OverwriteStorage(FileSystemStorage):

    def get_available_name(self, name, *args, **kwargs):

        # Delete all avatars in directory before adding new avatar.
        # (Sometimes we have different extension names, so we can't delete by name
        file_path = os.path.dirname(name)
        shutil.rmtree(os.path.join(settings.MEDIA_ROOT, file_path))

        return name

Проблема, которую я вижу, заключается в моей функции OverwriteStorage.Когда я удаляю это, это сохраняет.Как я могу исправить эту функцию, чтобы она перезаписывалась, если она существует?

1 Ответ

0 голосов
/ 23 июня 2019

Я думаю, что ваш идентификатор проблемы с instance.user.id Я бы посоветовал вам попытаться импортировать пользователя, как показано ниже:

from django.contrib.auth.models import User
user = User.objects.get(id=user_id)

def create_user_image_path(instance, image_name):
    image_name = str(user) + image_name[-4:]
    return 'users/{0}/avatars/{1}'.format(user.id, image_name)

Однако django рекомендует пользователю AUTH_USER_MODEL реализацию

from django.contrib.auth import get_user_model
User = get_user_model()

Обновление

Когда вы просматриваете хранилище переопределения, переменная name получает имя изображения, которое вы собираетесь загрузить.Ваш file_path = os.path.dirname(name), вы возвращаете папку с именем изображения.Когда shutil.rmtree связывается, чтобы найти папку, он возвращает ошибку и не может найти путь.Используйте условное выражение, например if или try except block, как показано ниже.

from django.core.files.storage import FileSystemStorage
from django.conf import settings
from django.core.files.storage import default_storage
import os


class OverwriteStorage(FileSystemStorage):

    def get_available_name(self, name, max_length=None):
        """Returns a filename that's free on the target storage system, and
        available for new content to be written to.

        Found at http://djangosnippets.org/snippets/976/

        This file storage solves overwrite on upload problem. Another
        proposed solution was to override the save method on the model
        like so (from https://code.djangoproject.com/ticket/11663):

        def save(self, *args, **kwargs):
            try:
                this = MyModelName.objects.get(id=self.id)
                if this.MyImageFieldName != self.MyImageFieldName:
                    this.MyImageFieldName.delete()
            except: pass
            super(MyModelName, self).save(*args, **kwargs)
        """
        # If the filename already exists, remove it as if it was a true file system
        if self.exists(name):
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
            # default_storage.delete(os.path.join(settings.MEDIA_ROOT, name))
        return name

Как и в вашем случае

class OverwriteStorage(FileSystemStorage):

    def get_available_name(self, name, *args, **kwargs):

        # Delete all avatars in directory before adding new avatar.
        # (Sometimes we have different extension names, so we can't delete by name
        if self.exists(name):
            file_path = os.path.dirname(name)
            shutil.rmtree(os.path.join(settings.MEDIA_ROOT, file_path))

        return name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...