首页 > 解决方案 > 外键可以连接到多个表吗?

问题描述

我有这样的 sqlalchemy 模型:

class Person(db.Model):
   ..
   # the photos of the person
   photos = db.relationship('Photos', lazy='dynamic')

class Photos(db.Model):
   ..
   #link to the photo
   link = db.Column(db.TEXT)

当然这会引发错误,我必须在照片表中包含外键连接到人。

问题是我想要照片表来托管其他对象的照片,比如汽车之类的东西。

如何使照片表连接到表的选项。请注意,如果 Person 没有其他表将连接到它,则 Photos 必须仅连接到一个表。

我希望这是有道理的

标签: pythonsqlalchemy

解决方案


该问题的严格关系数据库答案在这里,已经在 StackOverflow 上。严格来说,拥有一个可以指向多个表的外键并不被认为是“正确的”设计,而且数据库本身通常不直接支持它。

话虽如此,它仍然是一种常见的模式,特别是对于您的问题,您可能会查看一个名为SQLAlchemy-Utils的库,其中包含一个名为Generic Relationships的功能。考虑以下示例,来自文档:

from sqlalchemy_utils import generic_relationship

class User(Base):
    __tablename__ = 'user'
    id = sa.Column(sa.Integer, primary_key=True)

class Customer(Base):
    __tablename__ = 'customer'
    id = sa.Column(sa.Integer, primary_key=True)

class Event(Base):
    __tablename__ = 'event'
    id = sa.Column(sa.Integer, primary_key=True)

    # This is used to discriminate between the linked tables.
    object_type = sa.Column(sa.Unicode(255))

    # This is used to point to the primary key of the linked row.
    object_id = sa.Column(sa.Integer)

    object = generic_relationship(object_type, object_id)


# Some general usage to attach an event to a user.
user = User()
customer = Customer()

session.add_all([user, customer])
session.commit()

ev = Event()
ev.object = user

session.add(ev)
session.commit()

# Find the event we just made.
session.query(Event).filter_by(object=user).first()

# Find any events that are bound to users.
session.query(Event).filter(Event.object.is_type(User)).all()

event.object属性指向用户客户对象(或其他对象)。库通过组合object_type列“找到”另一个对象,告诉它要查询的其他表和object_id列。

这种方法有一些缺点,特别是在查询效率和索引方面,以及设计是否“感觉正确”。阅读我在上面链接到的那个答案,以讨论这个问题。


推荐阅读