Python 为什么每次使用“makemigrations”命令时Django都会生成新的迁移文件。对于具有已更改上载路径属性的ImageFIeld

Python 为什么每次使用“makemigrations”命令时Django都会生成新的迁移文件。对于具有已更改上载路径属性的ImageFIeld,python,django,django-models,Python,Django,Django Models,我需要在上传路径函数中获取ImageField名称。 我尝试在ImageField定义中使用partial: class MyModel(models.Model): image = models.ImageField( upload_to=partial(image_upload_path, 'image') ) 现在我可以通过函数的第一个参数获得该字符串: def image_upload_path(field, instance, filename):

我需要在
上传路径
函数中获取ImageField名称。
我尝试在ImageField定义中使用
partial

class MyModel(models.Model):

    image = models.ImageField(
        upload_to=partial(image_upload_path, 'image')
    ) 
现在我可以通过函数的第一个参数获得该字符串:

def image_upload_path(field, instance, filename):
    ....
一切正常,但现在Django生成迁移文件,每次我使用
makemigrations
,其中包含相同的
操作
列表:

operations = [
    migrations.AlterField(
        model_name='genericimage',
        name='image',
        field=core_apps.generic_image.fields.SorlImageField(upload_to=functools.partial(core_apps.generic_image.path.image_upload_path, *('image',), **{}),),
    ),
]

也许有另一种方法可以访问
upload\u path
函数中的字段名,或者我可以通过某种方式修复我的解决方案

在这种情况下,似乎不需要提供partial,只需提供一个带有两个参数的callable,就像Django文档中的一样

Django将使用两个参数(
instance
filename
)调用您在
upload\u to
参数中提供的可调用项

实例

定义文件字段的模型实例。更具体地说,这是附加当前文件的特定实例

这意味着您可以访问实例的
name
字段,如您编写的可调用文件中的
instance.name

class MyModel(models.Model):

    name = models.CharField(max_length=255)
    image = models.ImageField(upload_to=image_upload_path)


def image_upload_path(instance, filename):
    # Access the value of the `name` field
    # of the MyModel instance passed in and save it to a variable:
    name = instance.name

    # Code that returns a Unix-style path (with forward slashes) goes here

在这种情况下,您似乎不需要提供partial,只需要提供一个带有两个参数的callable,就像Django文档中的一样

Django将使用两个参数(
instance
filename
)调用您在
upload\u to
参数中提供的可调用项

实例

定义文件字段的模型实例。更具体地说,这是附加当前文件的特定实例

这意味着您可以访问实例的
name
字段,如您编写的可调用文件中的
instance.name

class MyModel(models.Model):

    name = models.CharField(max_length=255)
    image = models.ImageField(upload_to=image_upload_path)


def image_upload_path(instance, filename):
    # Access the value of the `name` field
    # of the MyModel instance passed in and save it to a variable:
    name = instance.name

    # Code that returns a Unix-style path (with forward slashes) goes here

我决定建立自己的领域:

class SorlImageField(ImageField):

    def __init__(self, verbose_name=None, name=None, width_field=None,
             height_field=None, lookup_name=None, **kwargs):
        self.lookup_name = lookup_name
        kwargs['upload_to'] = partial(image_upload_path, lookup_name)
        super(SorlImageField, self).__init__(verbose_name, name,
                                         width_field, height_field, **kwargs)

    def deconstruct(self):
        name, path, args, kwargs = super(SorlImageField, self).deconstruct()
        del kwargs['upload_to']
        # del upload_to will solve migration issue
        return name, path, args, kwargs

    def check(self, **kwargs):
        errors = super(SorlImageField, self).check(**kwargs)
        if self.lookup_name != self.name:
            error = [
                 checks.Error(
                'SorlImageField lookup_name must be equal to '
                'field name, now it is: "{}"'.format(self.lookup_name),
                hint='Add lookup_name in SorlImageField',
                obj=self,
                id='fields.E210',
            )]
        errors.extend(error)
    return errors
通过删除
upload\u to
参数,在
disconstruct
方法中解决了迁移问题。此外,我还在指向字段名的
初始化中添加了额外的参数,
检查
函数检查是否正确
查找\u名称
值。如果不是,则在迁移开始时将引发错误

class MyModel(models.Model):

    image = SorlImageField(
        lookup_name='image'
    ) 

我决定建立自己的领域:

class SorlImageField(ImageField):

    def __init__(self, verbose_name=None, name=None, width_field=None,
             height_field=None, lookup_name=None, **kwargs):
        self.lookup_name = lookup_name
        kwargs['upload_to'] = partial(image_upload_path, lookup_name)
        super(SorlImageField, self).__init__(verbose_name, name,
                                         width_field, height_field, **kwargs)

    def deconstruct(self):
        name, path, args, kwargs = super(SorlImageField, self).deconstruct()
        del kwargs['upload_to']
        # del upload_to will solve migration issue
        return name, path, args, kwargs

    def check(self, **kwargs):
        errors = super(SorlImageField, self).check(**kwargs)
        if self.lookup_name != self.name:
            error = [
                 checks.Error(
                'SorlImageField lookup_name must be equal to '
                'field name, now it is: "{}"'.format(self.lookup_name),
                hint='Add lookup_name in SorlImageField',
                obj=self,
                id='fields.E210',
            )]
        errors.extend(error)
    return errors
通过删除
upload\u to
参数,在
disconstruct
方法中解决了迁移问题。此外,我还在指向字段名的
初始化中添加了额外的参数,
检查
函数检查是否正确
查找\u名称
值。如果不是,则在迁移开始时将引发错误

class MyModel(models.Model):

    image = SorlImageField(
        lookup_name='image'
    ) 

实例-定义文件字段的模型实例。在我的例子中,它是
MyModel
not
ImageField
Django的ImageField的实例,带有一些额外的选项。将ImageField添加到
MyModel
类中。这不是您想要的吗?一个模型的
实例
return me实例,其中定义了名为
image
ImageField
。我需要
上传路径中的
名称
。无论如何,我写自定义字段,我会很快用答案更新它。感谢您尝试帮助instance—定义了文件字段的模型实例。在我的例子中,它是
MyModel
的实例,而不是
ImageField
Django的ImageField,还有一些额外的选项。将ImageField添加到
MyModel
类中。这不是您想要的吗?一个模型的
实例
return me实例,其中定义了名为
image
ImageField
。我需要
上传路径中的
名称
。无论如何,我写自定义字段,我会很快用答案更新它。谢谢你的帮助