【问题标题】:Django migrations and customizable reusable appsDjango 迁移和可定制的可重用应用程序
【发布时间】:2016-05-30 20:34:08
【问题描述】:

大约 3 周前,我开始编写我的第一个可重用应用程序,但在处理迁移时遇到了麻烦。

我希望我的应用程序的某些点是可定制的。因此我有一个conf submodule,它定义了自定义设置并分配了适合大多数情况的合理默认值。

这导致我的一些模型字段看起来像这样:

attachment = models.FilePathField(
    path=conf.ATTACHMENTS_DIR, recursive=True)

template_file = models.FileField(
    upload_to=conf.TEMPLATES_UPLOAD_DIR, blank=True)

prefix_subject = models.BooleanField(
    default=True, verbose_name=_("prefix subject"),
    help_text=_(
        "Whether to prefix the subject with \"{}\" or not."
    ).format(conf.SUBJECT_PREFIX))

不幸的是,在使用此应用的项目中,这会导致 django-admin makemigrations 在每次设置更改时为其创建迁移。甚至,他们第一次安装应用程序的设置,默认值取决于主机系统。

我非常怀疑在他的应用副本中创建自己的迁移的项目的合法性。但如果我错了,请告诉我。

对于上述示例中的prefix_subject,我使用this solution 解决了这个问题。考虑到在迁移中丢失help_text 信息并不是很有效。

但是,我不确定这是否适合所有/大多数情况。是吗?

我想到了另一种似乎可行的解决方案。此解决方案是手动编辑迁移并用变量本身替换评估的设置。

例如,我会替换这个:

migrations.CreateModel(
    name='MailStaticAttachment',
    fields=[
        ('id', ...),
        ('filename', ...)
        ('mime_type', ...)
        ('attachment', models.FilePathField(path='/home/antoine/Workspace/django-mailing/static/mailing/attachments', recursive=True, verbose_name='file')),
    ],
    options={...}
),

与:

from ..conf import ATTACHMENTS_DIR

migrations.CreateModel(
    name='MailStaticAttachment',
    fields=[
        ('id', ...),
        ('filename', ...)
        ('mime_type', ...)
        ('attachment', models.FilePathField(path=ATTACHMENTS_DIR, recursive=True, verbose_name='file')),
    ],
    options={...}
),

您觉得它是一个好的解决方案吗?

在这种情况下你建议怎么做?

我认为Field.help_textFilePathField.pathFileField.upload_to 属性都不用于创建SQL 语句。所以在这种情况下,不应该因为“在迁移中忽略它们”而出现具体问题。但是,假设我想要一个可定制的Field.defaultField.db_columnCharField.max_length 怎么办?这可能是一个非常糟糕的想法,没有实际意义,但这是我能找到的唯一假设情况。 :P 我想在这种情况下最好提供一个抽象的基础模型,以便由宿主项目扩展。

【问题讨论】:

    标签: python django django-migrations django-apps


    【解决方案1】:

    django.db.migration 的设计过程中,决定跟踪所有字段属性,即使它们不影响其架构表示。

    对于upload_to 的情况,我建议您只需传递在模块级别定义的函数as documented

    import os
    
    def upload_to(instance, filename):
        return os.path.join([conf.TEMPLATES_UPLOAD_DIR, filename])
    

    对于pathhelp_text,我建议您使用类似于我对django-sundial 所做的方法来提供可配置的默认值。你只需要确保你传递了一个带有deconstruct() method returning the appropriate parameters的类的实例。

    from django.utils.six import python_2_unicode_compatible
    
    
    @python_2_unicode_compatible
    class StringConfReference(object):
        def __init__(self, name):
            self.name = name
    
        def __str__(self):
            return getattr(conf, self.name)
    
        def deconstruct(self):
            return "%s.%s" % (__name__, self.__class__.__name__), (self.name,), {}
    
    
    attachment = models.FilePathField(
        path=StringConfReference('ATTACHMENT_DIR'), recursive=True
    )
    

    【讨论】:

    • 谢谢。我没想到会有更好的解决方案。这是我应用的补丁:github.com/Aladom/django-mailing/commit/… 生成的迁移看起来不错。 :)
    • 是的,使用deconstructible 更好。我建议使用 python_2_unicode_compatible 的原因是,如果您引用的设置之一包含非 ascii 字符,它将在 Python 2 上崩溃。
    • 是的。不过,我决定不关心 Python 2 的兼容性。我认为 Python 3 已被广泛采用。在可预见的未来,甚至 django 也会放弃对 python 2 的支持。
    • 不幸的是,django 逻辑使用os.listdir(path),它要求path 是一个字符串、字节或整数实例。我正在尝试解决这个问题。
    • 我开了一个关于这个问题的新问题:stackoverflow.com/questions/35632376/…
    猜你喜欢
    • 2015-03-22
    • 2019-06-19
    • 2016-09-28
    • 2018-10-19
    • 2018-10-19
    • 2016-04-14
    • 2011-04-24
    • 2014-05-01
    • 2020-07-03
    相关资源
    最近更新 更多