【发布时间】:2020-04-28 09:14:42
【问题描述】:
我有以下数据库结构:
class Word(models.Model):
original = models.CharField(max_length=40)
translation = models.CharField(max_length=40)
class Verb(Word):
group = models.IntegerField(default=1)
在我看来,我需要先创建一个Word 对象,确定其组后(取决于Word.original),创建一个Verb 对象,并保存。
从Word 类继承并将对象另存为Verb 的最佳方法是什么?
我尝试了几种解决方案:
1) 修改Verb 中的__init__ 方法:
class Verb(Word):
group = models.IntegerField(default=1)
def __init__(self, base_word):
self.original = base_word.original
self.translation = base_word.translation
这会导致很多错误,因为我覆盖了 django 的内置 __init__ 方法。
2) 使用super().__init__():
class Verb(Word):
group = models.IntegerField(default=1)
def __init__(self, base_word):
super().__init__()
self.original = base_word.original
self.translation = base_word.translation
显然,这很好用:
base_word = Word()
new_verb = Verb(base_word)
new_verb.save()
但是有两个问题:
- 尝试查看 django 管理页面中的对象时会导致错误:
__init__() takes 2 positional arguments but 9 were given
- 这还是代码太多,感觉不太对劲。我仍然需要这样写:
self.original = base_word.original
self.translation = base_word.translation
在每个子类中。这只是一个例子。在实际项目中,我有更多的领域。我想有一个更优雅的解决方案。
【问题讨论】:
-
为什么不将确定是否创建
Verb转移到表单。请不要覆盖__init__。 django 文档明确表示强烈建议不要覆盖__init__,尤其是not更改__init__的签名。 -
我可以提供更多细节。
Word有 4 个子类:Verb、Noun、Adjective、Pronoun。他们有很多共同的领域,所以我把他们放在Word。首先,我完成了Word中的所有这些字段,然后我创建了 4 个子类之一,而哪一个由表单确定。否则,在我看来,我将不得不编写相同的代码 4 次。 -
但据我所知,您可以只构造一个
Verb(original='foo', translation='bar', group=42),Django 将处理此问题并在Word和Verb的表中记录并正确链接. -
这正是我想要避免的。它有效,但同样,我必须为视图中的每个类填写相同的字段 4 次。
-
但是子类化在这里看起来不像是正确的工具。您可能想使用
OneToOneField制作模型,或者对abstract=True模型进行子类化。
标签: python django database django-models django-views