首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >建立一对多的模型参考抽象模型。

建立一对多的模型参考抽象模型。
EN

Stack Overflow用户
提问于 2012-08-02 18:48:21
回答 1查看 1.8K关注 0票数 4

我对Django非常陌生,现在我正在尝试理解抽象模型的使用。假设您正在编写博客服务,并且希望通过身份验证和匿名的用户都能够对博客文章进行评论。

虽然对于经过身份验证的用户来说,场景非常简单(只是有一个引用特定用户的外键),但是当Authors不仅仅是User,而是AnonymousAuthors或RegisteredAuthor的时候,情况就不那么简单了。

这里的直接方法是构建一个类的层次结构:

代码语言:javascript
复制
class Author(models.Model):
  class Meta:
    abstract = True

class AnonymousAuthor(Author):
  name = models.CharField(max_length=128)
  def display_name(self):
    return self.name

class RegisteredAuthor(Author):
  user = models.ForeignKey(User)
  def display_name(self):
    return self.user.user_name

然后可以这样定义BlogPostComment

代码语言:javascript
复制
class BlogPostComment(models.Model):
  author = models.ForeignKey(Author)
  ...

我喜欢这种方法,因为无论作者是谁,只要迭代BlogPostComment的集合并为每个注释调用display_name(),我就可以轻松地构建注释列表。这里唯一的问题是它不起作用。Django说:

代码语言:javascript
复制
AssertionError: ForeignKey cannot define a relation with abstract class Author

解决办法是什么?

更新

我知道泛型关系在这里能帮上忙。但这是唯一的解决办法吗?感觉有点过火了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-02 19:31:03

泛型关系是为许多人创建外键的解决方案,与模型不同。通常情况下,如果您有以下继承,则使用继承:

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

class Dog(Animal):
    ...

然后以后:

代码语言:javascript
复制
models.ForeignKey(Animal)

您也可以将Dog存储为外键,因为Dog是-一个Animal。但是,在抽象类的情况下,这些类不符合设置为外键目标的条件,因为它们不存在。Django的“抽象”模型更接近于“mixin”的定义:它们从未单独实例化过,而是用于组成其他实例化的类。

所以你有三个选择:

  1. Author改为标准模型,而不是抽象模型。然后,您可以创建Author的外键,并传入Author的任何子类。
  2. 使用通用外键
  3. 一开始不要拆散模特。

这里的最后一个选择实际上是您最好的选择,因为没有理由有单独的作者表,而唯一的定义差别是它们是注册的还是匿名的。这是对象的状态,而不是不同类型的对象。就像使用类似于BlueCar类的东西是不合适的。您有一个Car类,而"blue“是它的color属性的值。

如果你坚持要不同的模特。然后,您可以使用代理模型。其中,AnonymousAuthorRegisterAuthor只是Author的别名(它们没有自己的表),但是有了别名,您就可以更改或添加自定义方法,特别是能够指定一个自定义管理器,该管理器可以自动过滤Author以分别返回“匿名”或“注册”类型。

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

https://stackoverflow.com/questions/11783895

复制
相关文章

相似问题

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