本文介绍了如果django模型已经有相关类,如何将其转换为抽象模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下基本模型:

Lets say i have the following base model:

class human(models.Model):
   gender = models.BooleanField()
   age = models.IntegerField()
   name = models.CharField(max_length=200)

还有两个继承它的模型:

And two models inheriting it:

class superhero(human):
   can_fly = models.BooleanField()

class villain(human):
   fingerprint = models.ImageField()

在我的开发过程中的某个时候,我意识到我实际上并不直接需要人类类.我只需要它是一组超级英雄和反派模型的模板参数.如果现在我转到人类 Meta 类并设置 abstract=True 并像这样更改我的模型:

At some time in my development process i realized that i don't actually need the human class directly. I only need it to be a set of template parameters for superhero and villain models. If now i go to human Meta class and set abstract=True and change my models like so:

class human(models.Model):
   gender = models.BooleanField()
   age = models.IntegerField()
   name = models.CharField(max_length=200)

   class Meta:
       abstract = True

class superhero(human):
   can_fly = models.BooleanField()

class villain(human):
   fingerprint = models.ImageField()

尝试进行迁移和迁移将引发以下错误

attempt to make migrations and migrate will raise the following error

'superhero' 类中的本地字段 u'gender' 与基类 'human' 中名称相似的字段发生冲突

如何在不直接修改数据库的情况下切换到抽象类以保留所有迁移?

How can i switch to abstract class keeping all my migrations without tinkering the database directly?

推荐答案

所以在再次阅读文档后我找到了一个解决方案:

由于 Django 将模型保存到数据库的方式而引发的错误.从基本模型 human 继承的所有模型在它们自己的表中都没有所有 human 字段.相反,它们只有自己的字段和将它们链接到 human 表中相应行的外键.但是当您从抽象类继承时,所有字段都直接保存到模型的表中.因此,当我尝试将 human 类更改为 abstract=True 并在 superhero 类中继承它时,Django 尝试从 human 创建所有字段superhero 表中的 表,该表仍然具有指向现有人类条目的外键,其字段名称完全相同.

So after reading the docs again I found a solution:

The error was raised because of the way Django saves models to the database. All models that inherit from the base model human don't have all human fields in their own tables. Instead they have only their own fields and a foreign key that links them to the corresponding lines in human table. But when you inherit from abstract class all the fields are saved directly to your model's table. So when I tried to change human class to abstract=True and inherit it in superhero class Django tried to create all fields from human table in superhero table, which still has a foreign key to existing human entry with fields named exactly the same.

按照这个指令会得到想要的结果,但不幸的是会破坏所有条目 human superherovillain模型

Following this instruction will make the desired result but unfortunately will destroy all entries of human superhero and villain models

  1. 评论 superherovillain 模型,以便 Django 删除它们
  2. 进行迁移和迁移,以便删除 superherovillain
  3. human
  4. 中设置abstract=True
  5. 进行迁移并再次迁移.这将删除 human 表,因为它现在是一个抽象类
  6. 取消注释 superherovillain 模型
  7. 进行迁移和迁移.这将创建 villainsuperhero 表,其中包含 human
  8. 的所有字段
  1. Comment superhero and villain models so Django deletes them
  2. Make migrations and migrate so the superhero and villain tables are deleted
  3. Set abstract=True in human class
  4. Make migrations and migrate again. This will delete human table because now it is an abstract class
  5. Uncomment superhero and villain models
  6. Make migrations and migrate. This will create villain and superhero tables with all the fields from human class

就是这样.

附言为什么我需要转到抽象类?因为我想使用 unique_together 参数使我所有的 villainssuperheroes 都是独一无二的,这会产生一些数据库级别的限制.为了使这成为可能,所有 superhero 字段都必须在一个表中.现在它可以工作了.

P.S. Why I needed to move to abstract class? Because I wanted to make all my villains and superheroes unique using unique_together parameter that makes some DB level restrictions. To make this possible all superhero fields had to be in one table. Now it works.

这篇关于如果django模型已经有相关类,如何将其转换为抽象模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-24 14:33