创建一个新模型,其中包含当前现有模型的所有字段
Posted
技术标签:
【中文标题】创建一个新模型,其中包含当前现有模型的所有字段【英文标题】:Create a new model which have all fields of currently existing model 【发布时间】:2015-02-01 00:58:32 【问题描述】:我的 django 应用程序有一个模型 Player
。
class Player(models.Model):
""" player model """
name = models.CharField(max_length=100, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
hash = models.CharField(max_length=128, null=True, blank=True)
bookmark_url = models.CharField(max_length=300, null=True, blank=True)
根据我的要求,我需要创建一个新模型 BookmarkPlayer
,它将包含 Player
模型的所有字段。
现在我有两件事要做。
-
我可以为 BookmarkPlayer 模型扩展 Player 类。
-
我可以将 Player 模型的所有字段定义到 BookmarkPlayer 模型中。
我只是想知道哪种方法更好。如果有其他好的方法,请与我分享。
更新问题
Knbb 创建基类的想法很有趣,但我面临的问题是我的一个模型已经存在于数据库中。
我的实际模型:
类地址(模型。模型): 地址 = models.TextField(空=真,空白=真) 类站点(模型。模型): domain = models.CharField(max_length=200) 类播放器(模型。模型): # ... 其他字段 shipping_address = models.ForeignKey(地址,related_name='shipping') billing_address = models.ForeignKey(地址,related_name='billing') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now_add=True) 站点 = 模型.ManyToManyField(站点,null=True,空白=True) 元类: 摘要 = 真更改后的模型:
类地址(模型。模型): 地址 = models.TextField(空=真,空白=真) 类站点(模型。模型): domain = models.CharField(max_length=200) 类 BasePlayer(模型。模型): # .. 其他字段 shipping_address = models.ForeignKey(地址,related_name='shipping') billing_address = models.ForeignKey(地址,related_name='billing') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now_add=True) 站点 = 模型.ManyToManyField(站点,null=True,空白=True) 元类: 摘要 = 真 类播放器(BasePlayer): 元类: app_label = '核心' 类书签播放器(BasePlayer): 元类: app_label = '核心'在我运行 django 服务器时进行这些更改后,我收到以下错误。
django.core.management.base.CommandError:一个或多个模型未验证: core.test1:字段“shipping_address”的访问器与相关字段“Address.shipping”发生冲突。将related_name 参数添加到“shipping_address”的定义中。 core.test1:字段“shipping_address”的反向查询名称与相关字段“Address.shipping”冲突。将related_name 参数添加到“shipping_address”的定义中。 core.test1:字段“billing_address”的访问器与相关字段“Address.billing”发生冲突。在“billing_address”的定义中添加一个related_name 参数。 core.test1:字段“billing_address”的反向查询名称与相关字段“Address.billing”冲突。在“billing_address”的定义中添加一个related_name 参数。 core.test2:字段“shipping_address”的访问器与相关字段“Address.shipping”发生冲突。将related_name 参数添加到“shipping_address”的定义中。 core.test2:字段“shipping_address”的反向查询名称与相关字段“Address.shipping”冲突。将related_name 参数添加到“shipping_address”的定义中。 core.test2:字段“billing_address”的访问器与相关字段“Address.billing”发生冲突。在“billing_address”的定义中添加一个related_name 参数。 core.test2:字段“billing_address”的反向查询名称与相关字段“Address.billing”冲突。将相关名称参数添加到“帐单地址”的定义中答案: 最后,如果我们将 ForeignKey 或 ManyToManyField 上的 related_name 属性用于抽象模型,我得到了答案。 这通常会在抽象基类中引起问题,因为此类上的字段包含在每个子类中,并且每次的属性值(包括相关名称)完全相同。 要解决此问题,当您在抽象基类中使用related_name 时(仅),名称的一部分应包含“%(app_label)s”和“%(class)s”。https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes 现在我的 BasePlayer 模型是
类 BasePlayer(模型。模型): # .. 其他字段 shipping_address = models.ForeignKey(Address, related_name='%(app_label)s_%(class)s_shipping') billing_address = models.ForeignKey(Address, related_name='%(app_label)s_%(class)s_billing') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now_add=True) 站点 = 模型.ManyToManyField(站点,null=True,空白=True) 元类: 摘要 = 真【问题讨论】:
还有其他几种更好的方法可以做到这一点,但这取决于您的确切要求,哪一种是最好的。你首先想要两个模型的原因是什么? 我想将播放器详细信息添加为书签,以便在我的网站上共享用户之间的会话。 所以如果我理解正确,您基本上是想在特定时刻复制Player
的详细信息并将其另存为BookmarkPlayer
?在这种情况下,请参阅我的答案,那将是最好的方法。添加一些方便的方法也很容易将Player
转换为BookmarkPlayer
,反之亦然。
【参考方案1】:
这里有一些关于模型继承的好信息: https://docs.djangoproject.com/en/1.7/topics/db/models/#model-inheritance
选项 2 会引入重复,这总是不好的。如果BookmarkPlayer
没有任何新字段,只有不同的方法,我建议您使用链接中描述的“代理模型”选项,因为您不需要BookmarkPlayer
在数据库中拥有自己的表。
如果它需要它自己的表,“多表继承”是要走的路,这将是您问题中的选项 1
【讨论】:
BookmarkPlayer 需要有自己的表进入数据库。 @PrashantGaur 我更新了答案以涵盖该场景 @knbk 当然是对的,多表继承只会将额外的BookmarkPlayer
字段保存在新表中。他的回答更好:)
@PrashantGaur 我想将相关名称更改为不同的名称值得尝试。但它在我的机器上验证了。你使用的是哪个 django 版本?
我正在使用 Django1.3。请在我的问题中查看更新。我知道为什么会出现错误。【参考方案2】:
如果您的BookmarkPlayer
需要相同的数据但在不同的表中,则最好使用抽象基础模型:
class BasePlayer(models.Model):
name = models.CharField(max_length=100, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
hash = models.CharField(max_length=128, null=True, blank=True)
bookmark_url = models.CharField(max_length=300, null=True, blank=True)
class Meta:
abstract = True
class Player(BasePlayer):
""" player model """
pass
class BookmarkPlayer(BasePlayer):
""" bookmark player model """
pass
这样,Player
和BookmarkPlayer
都从BasePlayer
模型中继承了它们的字段,但是因为BasePlayer
是抽象的,所以模型完全解耦了。
另一方面,多表继承仍会将字段保存在单个表中,但会为BookmarkPlayer
添加一个额外的表,并在Player
表中添加一个隐含的OneToOneField
。
【讨论】:
我尝试根据您的建议创建一个抽象性质的基类,但通过使用它我无法验证我的模型。请参阅更新后的问题以上是关于创建一个新模型,其中包含当前现有模型的所有字段的主要内容,如果未能解决你的问题,请参考以下文章