大约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()方法返回适当的参数。
导入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迁移和可自定义的可重用应用程序
发布评论