【问题标题】:database for tags - updating many-to-many tables with unique columns标签数据库 - 使用唯一列更新多对多表
【发布时间】:2014-06-29 11:08:52
【问题描述】:

我对数据库不是很有经验,可能完全走错了路。

我有两个表,链接和标签,以及一个关联表。我想用一个看起来像row = [tag, link] 的输入来更新这个数据库,但我想确保我没有添加任何已经存在的标签或链接。所以我先测试链接是否存在,然后标签是否存在,最后关联是否存在。

表格如下所示:

tagslinks_assoc = Table(
    'tagslinks', Base.metadata,
    # Column('id', Integer, primary_key=True),  # Not sure if this is required
    Column('tagid', Integer, ForeignKey('tags.tagid')),
    Column('linkid', Integer, ForeignKey('links.linkid')))

class Tags(Base):
    __tablename__ = 'tags'    
    tagid = Column(Integer, primary_key=True)
    tag   = Column(String, unique=True)
    links = relationship("Links", secondary=tagslinks_assoc, backref="tags")

class Links(Base):
    __tablename__ = 'links'    
    linkid    = Column(Integer, primary_key=True)
    link      = Column(String, unique=True)

我正在检查链接和标签是否存在:

link = session.query(Links).filter(Links.link == row[1]).first()
tag = session.query(Tags).filter(Tags.tag == row[0]).first()

如果标签和链接都已经存在但尚未连接,我将如何更新它们之间的关联?

在 sqlalchemy 和/或数据库关系中是否有什么东西让整个方法变得多余?

我在 this example 工作,以了解如何创建多对多关系,但我的领域都是独一无二的。也许他们不应该?

【问题讨论】:

    标签: python database-design sqlalchemy


    【解决方案1】:

    你快到了。默认情况下,关系类似于列表,因此只需附加一个项目就会创建一个新的关联。相反,使它们类似于集合以检测重复项。集合中的东西需要覆盖__hash__,以便正确检测到重复项。

    class Tags(Base):
        # ...
    
        links = relationship(
            'Links', tagslinks_assoc,
            collection_class=set,  # use a set to hold the collection
            backref=backref('tags', collection_class=set)
        )
    
        def __hash__(self):
            return hash((self.__class__, self.tag))  # any Tag with the same name hashes equal
    
    class Links(Base):
        # ...
    
        def __hash__(self):
            return hash((self.__class__, self.link))
    

    现在获取标签,并将其添加到链接中。如果它已经存在,什么都不会发生。

    tag = session.query(Tags).filter(Tags.tag == 'my_tag').first()
    link = session.query(Link).filter(Links.link == 'my_link').first()
    
    link.tags.add(tag)  # if it's already present, the hash will compare equal and nothing will happen
    session.commit()
    

    请参阅有关 collection_class 的文档。

    关于您的 tagslinks_assoc 表,在大多数情况下,每个表都应该有一个主键。在这种情况下,键将是 tagid 和 linkid 的组合。

    tagslinks_assoc = Table(
        'tagslinks', Base.metadata,
        Column('tagid', Integer, ForeignKey('tags.tagid'), primary_key=True),
        Column('linkid', Integer, ForeignKey('links.linkid'), primary_key=True)
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多