我有一个Django模型做得太多了。这是该模型的缩写示例。基本上,它可以表示四种不同的Entity
类型,并且存在指向其他实体的递归ForeignKey和ManyToMany关系。
这个项目目前正在使用Django 1.8.x和Python 2.7.x,但如果解决方案需要,我可以升级它们。
class Entity(models.Model):
"""
Films, People, Companies, Terms & Techniques
"""
class Meta:
ordering = ['name']
verbose_name_plural = 'entities'
# Types:
FILM = 'FILM'
PERSON = 'PERS'
COMPANY = 'COMP'
TERM = 'TERM'
TYPE_CHOICES = (
(FILM, 'Film'),
(PERSON, 'Person'),
(COMPANY, 'Company'),
(TERM, 'Term/Technique'),
)
created = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
type = models.CharField(max_length=4, choices=TYPE_CHOICES, default=FILM)
slug = models.SlugField(blank=True, unique=True, help_text="Automatically generated")
name = models.CharField(max_length=256, blank=True)
redirect = models.ForeignKey('Entity', related_name='entity_redirect', blank=True, null=True, help_text="If this is an alias (see), set Redirect to the primary entry.")
cross_references = models.ManyToManyField('Entity', related_name='entity_cross_reference', blank=True, help_text="This is a 'see also' — 'see' should be performed with a redirect.")
[... and more fields, some of them type-specific]
我意识到这是相当混乱的,我想删除'键入'并创建一个EntityBase
类来抽象出所有常见字段,并创建新的Film
,Person
,Company
和Term
模型EntityBase
抽象基类。
创建新模型后,我想我了解如何编写数据迁移以将所有字段数据移动到新模型(迭代Entity
上的对象,通过type
过滤,在适当的新模型中创建新对象)... 除了 ForeignKey和ManyToMany关系。也许我正在以错误的方式思考这个问题,但是如果在迁移过程中,关系指向的新对象可能还不存在,我怎样才能转移这些关系?
我怀疑这可能意味着多步迁移,但我还没有找到正确的方法来实现这一目标。
答案 0 :(得分:1)
m2m和fk字段没什么神奇之处。这是我要遵循的程序......可能有点生硬,但会完成工作:
for
循环。在实践中,这意味着从“BACKKKUPPPPPPppp”恢复很多,直到迁移恰到好处。
要照顾的一件小事:
如果尚未保存模型,则M2m字段无法获取任何值(因为模型在首次保存时获取其ID)。我会在手动迁移中做一些事情:
new_instance = NewModel()
new_instance.somefield = "whatever"
new_instance.meaning = 42
....
new_instance.save()
new_instance.that_m2m_field.add(some_related_obj)
当然,请务必详细阅读the docs,特别是有关导入模型类的内容 - 您不能只导入 ,而是: from myapp.models import MyModel
MyModel = apps.get_model("myapp", "MyModel")
一种可能的绊脚石可能是您计划引入的模型继承。通常,您需要对子模型进行操作,并根据需要从那里访问父项。可以通过隐式ptr
属性访问父级 - 在您的示例中,它将是entitybase_ptr
或类似的东西(只是OneToOne字段)。然而,朝着另一个方向前进(从父母到未知的孩子)并不那么简单,因为父母不知道其孩子的等级是什么。