Django迁移和可自定义的可重用应用程序 [英] Django migrations and customizable reusable apps

查看:80
本文介绍了Django迁移和可自定义的可重用应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大约3周前,我开始编写我的第一个可重用应用程序,但是我在处理迁移方面遇到了麻烦。可定制的。因此,我有一个 conf 子模块,用于定义自定义设置并分配适合大多数情况的合理默认值。



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

 附件= models.FilePathField(
path = conf.ATTACHMENTS_DIR,递归= True)

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

prefix_subject = models.BooleanField(
default = True,verbose_name = _(前缀主题),
help_text = _(
是否给主题加上\ {} \前缀。
).format(conf.SUBJECT_PREFIX))

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



我对创建它的项目的合法性表示怀疑在他的应用副本中进行自己的迁移。



对于上述示例中的 prefix_subject ,我解决了此解决方案。考虑到在迁移过程中丢失 help_text 信息不是很有效。



但是,我不确定这是适用于所有/大多数情况的解决方案。是吗?



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



例如,我将替换为:

  migrations.CreateModel(
name ='MailStaticAttachment',
个字段= [
('id',...),
('文件名',...)
('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',...),
('文件名',...)
('mime_type',...)
('附件',models.FilePathField(path = ATTACHMENTS_DIR,递归= True,verbose_name ='file') ),
],
options = {...}
),

对您来说这似乎是一个很好的解决方案吗?



您有什么建议



我认为 Field.help_text FilePathField.path FileField.upload_to 属性不用于创建SQL语句。因此,在这种情况下,由于在迁移中忽略它们,因此不应存在特定问题。但是,假设我想要一个可自定义的 Field.default Field.db_column 怎么办?例如CharField.max_length ?这可能是一个很糟糕的主意,没有实际意义,但这是我能找到的唯一假设情况。 :PI猜测在这种情况下,最好提供一个抽象的基础模型,以供宿主项目扩展。

解决方案

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



对于 upload_to 的情况,我建议您只传递在模块级别已记录

  import os 

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

对于路径 help_text 我建议您使用与 django-sundial 来提供可配置的默认值。您只需要确保通过具有 deconstruct()方法返回适当的参数

 <从django.utils.six中的code>导入python_2_unicode_compatible 


@ python_2_unicode_compatible
类StringConfReference(object):
def __init __(self,name):
self.name =名称

def __str __(self):
return getattr(conf,self.name)

def deconstruct(self):
返回%s。%s%(__name__,self .__ class __.__ name__),(self.name,),{}


附件= models.FilePathField(
path = StringConfReference('ATTACHMENT_DIR'),递归= True


I started writing my first reusable app about 3 weeks ago, and I'm having troubles to deal with migrations.

I want some points of my app to be customizable. Thus I have a conf submodule that defines custom settings and assign the reasonable defaults that will fit most cases.

This leads some of my model fields to look like this:

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

Unfortunately, on projects using this app, this causes django-admin makemigrations to create migrations for it every time a setting changes. Or even, the first time they install the app for settings which default value depends on the host system.

I'm more than doubtful about the legitimacy of a project creating its own migrations inside his copy of an app. But if I'm wrong, tell me.

For prefix_subject in the above sample, I solved the issue with this solution. Considering that losing the help_text information in migrations was not very effective.

However, I'm not sure this is a suitable solution for all/most cases. Is it?

I thought about another solution that seems to work. This solution is to manually edit migrations and replace evaluated settings by the variable itself.

For instance, I would replace this:

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={...}
),

With :

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={...}
),

Does it look like a good solution to you?

What do you advise to do in such cases?

I think both Field.help_text, FilePathField.path and FileField.upload_to attributes are not used to create SQL statements. So in this case, there should not be specific issues due to "ignoring them in migrations". But what if I, hypothetically, want a customizable Field.default, Field.db_column or CharField.max_length for instance? That's probably a very bad idea that have no practical interest, but that's the only hypothetical situation I can find. :P I guess in this case it would be better to provide an abstract base model, intended to be extended by the host project.

解决方案

During the design of django.db.migration it was decided that all field attributes were to be tracked even if they didn't affect their schema representation.

For the upload_to case I suggest you simply pass a function defined at a module level as documented.

import os

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

For the path and help_text I suggest you use an approach similar to what I did with django-sundial to provide configurable defaults. You'll just have to make sure you pass an instance of a class with a 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
)

这篇关于Django迁移和可自定义的可重用应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆