首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django多表继承:在子模型之间移动实例

Django多表继承:在子模型之间移动实例
EN

Stack Overflow用户
提问于 2018-02-18 12:59:38
回答 1查看 690关注 0票数 1

假设我在models.py中有如下内容:

代码语言:javascript
复制
Class ModelA(models.Model):
    # many fields, including
    relatives = models.ManyToManyField(Person)
)

# also, A is foreign key to other models:
Class SomeOtherModel(models.Model):
    mya = models.ForeignKey(A)

# now we produce two classes with multi-table inheritance
# WITHOUT any additional fileds
Class InhertA1(ModelA):
    pass

Class InhertA2(ModelA):
    pass

正如我所理解的,这将为ModelAInheritA1InheritA1创建表;ModelA的每个实例只在ModelA-table中得到一行,InheritA1的每个实例将在ModelA-table (基本上包含所有数据)和InheritA1-table (仅包含一个PK和指向ModelA-table行的OneToOne键)中都有一行,等等。Django查询ModelA-对象将给出所有对象,对InheritA1-对象的查询仅为InheritA1对象等等。

所以现在我有了一个InheritA1-object a1,并且想把它变成一个InheritA2-object,而不需要更改a ModelA-object。因此,在此之前,a1的父键IbeToOne指向ModelA-row,例如,键3 (并且某些SomeOtherModel-object的ForeignKey设置为3)。最后,我想要一个InheritA1-object a2指向相同的、不变的ModelA-row (并且删除了对象a1)。

似乎django没有提供任何这样的移动类功能?

我能自己安全地实现相应的SQL操作吗?

还是会发生可怕的错误?也就是说,我可以执行以下SQL命令吗?

  1. InheritA2-table中创建一个新行,将父-OneToOne键设置为a1
  2. 删除InheritA2-table中的InheritA2行?

看来,如果不自动创建ModelA-row,我就无法在非SQL中完成这一任务。那么,对于1。也许我可以这样创建一个临时对象x,然后让p成为x的父对象,然后将x的父-OneToOne键更改为指向a1的对象,然后删除obect p?但是对于2,我认为在非SQL中不可能在保留父对象的同时移除子实例?

或者,是否有一种好的django方法来复制django中的实例并更改对它们的引用?

也就是说,我可以创建一个新的InheritA2对象y,并将a1的所有属性复制到新对象中,然后遍历数据库,找到指向a1父对象的所有ManyToMany和ForeignKey条目,然后将其更改为指向y的父对象,然后删除a1

这可以用非SQL-django来实现,缺点是它似乎浪费了性能(这对我的项目没有太大的影响),而且它可能也不是那么“稳定”,也就是说,如果我更改ModelA或其他与它相关的模型,复制所有内容的代码可能会中断?)或者有什么好的方法来做类似的事情

代码语言:javascript
复制
Forall models M in my project:
    Forall keys k used in M:
        If k is a descendant of a ManyToMany or Foreign or  ... key:
            If k points to ModelA:
                Forall instances x of M:
                    If x.k=a1:
                        x.k=y

前四行似乎相当可疑。

备注:

  • 复制而不更改实例可以以稳定、简单、标准的方式完成,例如here,但是我们仍然被困在同一个子类中(还必须修改ForeignKeys等)?
  • 通过用标准的python方式声明类(请参阅here )来更改类对我来说不是一个选项,因为似乎没有人知道它是否会严重破坏django。
EN

回答 1

Stack Overflow用户

发布于 2018-04-21 19:16:30

如果您计划更改子级而不是父级,那么也许可以使用OneToOneField而不是直接继承。

代码语言:javascript
复制
class ModelA(models.Model):
    pass

class InhertA1(models.Model):
    a = models.OneToOneField(ModelA, primary_key=True)

class InhertA2(models.Model):
    a = models.OneToOneField(ModelA, primary_key=True)

它给出了数据库中相同的3个表。(一个不同之处是,InheritA1InheritA2的pk字段将是父字段的相同id。)

为了从InheritA1更改为InheritA2,您将删除一个子实例(这不会影响父实例),然后创建另一个新实例,将其指向父实例。

您甚至可以拥有一个父实例,其中包含来自其他两个模型的子实例,但是在您的视图中将检查该实例以防止这种情况发生。

让我知道这是否对你有帮助,即使答案有点晚。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48851951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档