小能豆

Django 迁移和可解构字符串

py

我必须创建一个类,其实例必须符合两个条件:

  • 作为一个str子类,以便可以传递给os.listdir()
  • 可解构,因此当 django 生成迁移时,字符串不会按原样出现,而是作为mailing.conf.StrConfRef('another string')

以下是我尝试过的:

class StrConfRef(str):

    def __new__(cls, name, within=None):
        value = globals()[name]
        if within:
            value = within.format(value)
        self = str.__new__(cls, value)
        self.name = name
        self.within = within
        return self

    def deconstruct(self):
        return ('{}.{}'.format(__name__, self.__class__.__name__), (self.name,),
                {'within': self.within})

第一点值得尊重os.listdir(StrConfRef(...))。然而,它在迁移中仍然被评估为“标准字符串”。我检查了一下django.db.migrations.autodetector,发现当代码执行时,StrConfRef 实例会到达这一行(这是预料之中的,应该意味着 StrConfRef 被正确解构了)。

所以我想知道为什么它在我的迁移中显示为字符串,而不是 mailing.conf.StrConfRef 实例。以及如何满足我的条件。


阅读 74

收藏
2025-02-26

共1个答案

小能豆

不幸的是,看起来具有deconstruct()方法的对象并不比str 子类具有优先级。

您可以在这里使用django.db.migrations.writer.SettingsReference看起来优先于的类str

我建议你创建一个自定义字段子类,默认为你的conf字段值。例如,你Campaign.prefix_subject可以是这个类的一个实例:

class PrefixSubject(models.BooleanField):
    default_help_text = (
        'Wheter to prefix the subject with "{}" or not.' % conf.SUBJECT_PREFIX
    )

    def __init__(self, *args, **kwargs):
        kwargs.setdefault('help_text', default_help_text)
        super().__init__(*args, **kwargs)

    def deconstruct(self):
        name, path, args, kwargs = super().deconstruct()
        if kwargs['help_text'] == self.default_help_text:
            kwargs.pop('help_text')
        return name, path, args, kwargs
2025-02-26