복붙노트

[PYTHON] 장고 - 동적 upload_to 값으로 ImageField에 대한 이전을 만들 수 없습니다.

PYTHON

장고 - 동적 upload_to 값으로 ImageField에 대한 이전을 만들 수 없습니다.

방금 내 앱을 1.7로 업그레이드했습니다 (실제로는 아직 시도 중입니다).

이것은 models.py에서 내가 가진 것입니다.

def path_and_rename(path):
    def wrapper(instance, filename):
        ext = filename.split('.')[-1]
        # set filename as random string
        filename = '{}.{}'.format(uuid4().hex, ext)
        # return the whole path to the file
        return os.path.join(path, filename)
    return wrapper

class UserProfile(AbstractUser):
    #...
    avatar = models.ImageField(upload_to=path_and_rename("avatars/"),
                               null=True, blank=True,
                               default="avatars/none/default.png",
                               height_field="image_height",
                               width_field="image_width")

내가 makemigrations하려고하면 던졌습니다 :

ValueError: Could not find function wrapper in webapp.models.
Please note that due to Python 2 limitations, you cannot serialize unbound method functions (e.g. a method declared
and used in the same class body). Please move the function into the main module body to use migrations.

해결법

  1. ==============================

    1.내 자신의 질문에 답하는 것이 괜찮은지 확실하지 않지만, 나는 생각했다.

    내 자신의 질문에 답하는 것이 괜찮은지 확실하지 않지만, 나는 생각했다.

    이 버그 보고서에 따르면, 나는 나의 코드를 편집했다 :

    from django.utils.deconstruct import deconstructible
    
    @deconstructible
    class PathAndRename(object):
    
        def __init__(self, sub_path):
            self.path = sub_path
    
        def __call__(self, instance, filename):
            ext = filename.split('.')[-1]
            # set filename as random string
            filename = '{}.{}'.format(uuid4().hex, ext)
            # return the whole path to the file
            return os.path.join(self.path, filename)
    
    path_and_rename = PathAndRename("/avatars")
    

    그리고 필드 정의에서 :

    avatar = models.ImageField(upload_to=path_and_rename,
                                   null=True, blank=True,
                                   default="avatars/none/default.png",
                                   height_field="image_height",
                                   width_field="image_width")
    

    이것은 나를 위해 일했다.

  2. ==============================

    2.동일한 문제가 있었지만 많은 이미지 파일이 내 모델에 있습니다.

    동일한 문제가 있었지만 많은 이미지 파일이 내 모델에 있습니다.

    head = ImageField(upload_to=upload_to("head")
    icon = ImageField(upload_to=upload_to("icon")
    ...etc
    

    내가 가진 모든 ImageField 열에 대해 upload_to wraper func을 생성하고 싶지 않습니다.

    그래서 나는 wrapper라는 이름의 func을 만들고 작동한다.

    def wrapper():
        return
    

    마이그레이션 파일을 열었으므로이 파일이 정상적으로 작동한다고 생각합니다.

    ('head', models.ImageField(upload_to=wrapper)),
    

    나는 그것이 마이그레이션 과정에 영향을 미치지 않는다고 생각한다.

  3. ==============================

    3.다음과 같이 kwargs 함수를 만들 수 있습니다 :

    다음과 같이 kwargs 함수를 만들 수 있습니다 :

    def upload_image_location(instance, filename, thumbnail=False):
        name, ext = os.path.splitext(filename)
        path = f'news/{instance.slug}{f"_thumbnail" if thumbnail else ""}{ext}'
        n = 1
        while os.path.exists(path):
            path = f'news/{instance.slug}-{n}{ext}'
            n += 1
        return path
    

    그리고이 메소드를 모델의 functools.partial과 함께 사용하십시오.

    image = models.ImageField(
        upload_to=upload_image_location,
        width_field='image_width',
        height_field='image_height'
    )
    thumbnail_image = models.ImageField(upload_to=partial(upload_image_location, thumbnail=True), blank=True)
    

    다음과 같이 마이그레이션 할 수 있습니다.

    class Migration(migrations.Migration):
    
        dependencies = [
            ('news', '0001_initial'),
        ]
    
        operations = [
            migrations.AddField(
                model_name='news',
                name='thumbnail_image',
                field=models.ImageField(blank=True, upload_to=functools.partial(news.models.upload_image_location, *(), **{'thumbnail': True})),
            ),
            migrations.AlterField(
                model_name='news',
                name='image',
                field=models.ImageField(height_field='image_height', upload_to=news.models.upload_image_location, width_field='image_width'),
            ),
        ]
    
  4. from https://stackoverflow.com/questions/25767787/django-cannot-create-migrations-for-imagefield-with-dynamic-upload-to-value by cc-by-sa and MIT license