Django - Cannot create migrations for ImageField with dynamic upload_to value

前端 未结 3 1008
隐瞒了意图╮
隐瞒了意图╮ 2020-12-05 04:34

I just upgraded my app to 1.7 (actually still trying).

This is what i had in models.py:

def path_and_rename(path):
    def wrapper(instance, filenam         


        
相关标签:
3条回答
  • 2020-12-05 05:03

    You can create function with kwargs like this:

    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
    

    and use this method with functools.partial in your model:

    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)
    

    You will get migration like this:

    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'),
            ),
        ]
    
    0 讨论(0)
  • 2020-12-05 05:05

    I had the same problem but I have many ImageFile in my models

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

    I don't want create upload_to wraper func for every ImageField column I have.

    So I just create a func named wrapper, and it woks

    def wrapper():
        return
    

    I think it works just fine because I opened migration file and I found this:

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

    I guess it's not effect migration process

    0 讨论(0)
  • 2020-12-05 05:07

    I am not sure if it is OK to answer my own question, but i just figured out (i think).

    According to this bug report, i edited my code:

    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")
    

    And then, in field definition:

    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")
    

    This worked for me.

    0 讨论(0)
提交回复
热议问题