简体   繁体   English

定义一个SQLAlchemy模型与其他多个模型之一相关

[英]Define one SQLAlchemy model to be related to one of multiple other models

I'm designing the database for my own Q&A website, which is somewhat similar to Stack Overflow: 我正在为自己的问答网站设计数据库,该网站与Stack Overflow有点类似:

  1. A "question" can have several "answers", but an "answer" has only one "question". 一个“问题”可以有多个“答案”,但是一个“答案”只有一个“问题”。
  2. Both "questions" and "answers" can have several "comments", but a "comment" has only one "question" or "answer". “问题”和“答案”都可以有多个“评论”,但是“评论”只有一个“问题”或“答案”。

I have no idea how to design such a database. 我不知道如何设计这样的数据库。 Here is what I've tried: 这是我尝试过的:

class Question(db.Model):
    __tablename__ = 'questions'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.Unicode(64), unique=True)
    body = db.Column(db.UnicodeText)
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    answers = db.relationship('Answer', backref='question', lazy='dynamic')

class Answer(db.Model):
    __tablename__ = 'answers'
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.UnicodeText)
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    question_id = db.Column(db.Integer, db.ForeignKey('questions.id'))

class Comment(db.Model):
    __tablename__ = 'comments'
    id = db.Column(db.Integer, primary_key=True)
    # post_id = db.Column(db.Integer, db.ForeignKey('')) ???

So you've already managed the first point. 因此,您已经掌握了第一点。

What you're looking for is a generic relationship. 您正在寻找的是一种通用的关系。 You can find it in sqlalchemy_utils package. 您可以在sqlalchemy_utils包中找到它。

from sqlalchemy_utils import generic_relationship


class Comment(db.Model):
    __tablename__ = 'comments'
    id = db.Column(db.Integer, primary_key=True)
    object_type = db.Column(db.Unicode(255))
    object_id = db.Column(db.Integer)
    object = generic_relationship(object_type, object_id)

Docs for generic relationship 通用关系文档

So basically what it does, it stores the object_type as answer or question and object_id as object's primary key. 因此,基本上它会做什么,它将object_type存储为答案或问题,而将object_id为对象的主键。

I suggest you extract a base class for Question and Answer, eg Post, and make Comment relate to Post, such that a Post can have multiple Comments. 我建议您为“问答”提取一个基类,例如“帖子”,并使“注释”与“帖子”相关,以便“帖子”可以有多个“注释”。

SQLAlchemy ORM supports few strategies to implement inheritance in the database , and the right strategy to choose depends on the way you plan to query your entities. SQLAlchemy ORM不支持在数据库中实现继承的几种策略,正确的选择策略取决于您计划查询实体的方式。 Here's the detailed documentation on how to properly configure it . 这是有关如何正确配置它详细文档

So you'd get something like this: 因此,您将获得如下内容:

(disclaimer: I have not directly ran this code, but composed it from your example, and my own code. If it ain't working for you, let me know and I'll fix) (免责声明:我没有直接运行此代码,而是由您的示例和我自己的代码组成的。如果它对您不起作用,请告诉我,我会解决)

class Post(db.Model):
    __tablename__ = 'posts'

    id = db.Column(db.Integer, primary_key=True)
    kind = Column(db.Unicode(64), nullable=False)
    body = db.Column(db.UnicodeText)
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    comments = db.relationship('Comment', backref='post', lazy='dynamic')

    __mapper_args__ = {
        'polymorphic_identity': 'posts',
        'polymorphic_on': kind
    }

class Question(Post):
    __tablename__ = 'questions'

    title = db.Column(db.Unicode(64), unique=True)
    answers = db.relationship('Answer', backref='question', lazy='dynamic')

    __mapper_args__ = {
        'polymorphic_identity': 'questions',
    }

class Answer(Post):
    __tablename__ = 'answers'

    question_id = db.Column(db.Integer, db.ForeignKey('questions.id'))

    __mapper_args__ = {
        'polymorphic_identity': 'answers',
    }

class Comment(db.Model):
    __tablename__ = 'comments'

    id = db.Column(db.Integer, primary_key=True)
    post_id = db.Column(db.Integer, db.ForeignKey('posts.id'))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM