在Flask SQLAlchemy关联表中保存重复条目

2 投票
1 回答
1254 浏览
提问于 2025-04-17 23:11

我正在设计一个系统,用来记录哪个用户拥有哪些显示器。

在这个系统中,我们有用户。每个用户可以拥有零个或多个显示器。

而且,一个用户可以拥有多个相同的显示器。

这是我的用户类:

class User(db.Model):
    id = db.Column(db.Integer, db.Sequence('user_id_seq'), 
                   autoincrement=True, primary_key=True)

    login = db.Column(db.String(140), unique=True)

    def __init__(self, login):
        self.login = login

    def __repr__(self):
        return '<User %r>' % self.login

这是我的审计类:

class Audit(db.Model):
    id = db.Column(db.Integer, db.Sequence('audit_id_seq'), 
                   autoincrement=True, primary_key=True)

    start_date = db.Column(db.DateTime)
    end_date = db.Column(db.DateTime)

    def __init__(self):
        self.start_date  = datetime.now()

    def __repr__(self):
        return '<Audit %r>' % self.id

这是我的显示器类:

class Monitor(db.Model):
    id = db.Column(db.Integer, db.Sequence('monitor_id_seq'), 
                   autoincrement=True, primary_key=True)

    description = db.Column(db.String(140), unique=True)

    def __init__(self, description):
        self.description = description

    def __repr__(self):
        return '<Monitor %r>' % self.description

这是我的用户审计类:

class UserAudit(db.Model):
    id = db.Column(db.Integer, db.Sequence('user_audit_id_seq'), 
                   autoincrement=True, primary_key=True)

    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    user = db.relationship('user',
        backref=db.backref('user_audits', lazy='dynamic'))

    audit_id = db.Column(db.Integer, db.ForeignKey('audit.id'))
    audit = db.relationship('Audit')

    monitors = db.relationship('Monitor', 
                                secondary=userAuditMonitor.association_table,
                                backref='user_audit_monitors')

    def __init__(self, user, audit):
        self.user = user
        self.audit = audit

    def __repr__(self):
        return '<UserAudit %r>' % self.id 

最后,这是我的用户审计显示器类,它把所有的内容连接在一起:

class UserAuditMonitor():
    association_table = Table('user_audit_monitor', db.Model.metadata,
        Column('user_audit_id', db.Integer, db.ForeignKey('user_audit.id')),
        Column('monitor_id', db.Integer, db.ForeignKey('monitor.id'))
    )

上面的关联表非常有用,因为我可以简单地使用 .append() 方法,把更多的显示器添加到一个用户审计的 sqlalchemy 对象中。

举个例子:

>>> u = UserAudit.query.get(1)
>>> monitors = [Monitor.query.get(3), Monitor.query.get(4)]
>>> u.append(monitors)
>>> print u.monitors
[<Monitor u'HP'>, <Monitor u'Dell'>]
>>> db.session.commit()
>>> print u.monitors
[<Monitor u'HP'>, <Monitor u'Dell'>]

但是,如果我尝试把多个相同的显示器添加到一个用户审计对象中,最终只会存储一个显示器。

举个例子:

>>> u = UserAudit.query.get(2)
>>> monitors = [Monitor.query.get(3), Monitor.query.get(3)]
>>> u.append(monitors)
>>> print u.monitors
[<Monitor u'HP'>, <Monitor u'HP'>]
>>> db.session.commit()
>>> print u.monitors
[<Monitor u'HP'>] # ONLY ONE MONITOR GOT SAVED HERE!!!

我该如何配置用户审计显示器类,以便保存重复的显示器呢?

谢谢!

1 个回答

1

我猜测 UserAuditMonitor 这个表没有明确设置主键,所以SQLA(一个数据库工具)就用 user_audit_id x monitor_id 这两个字段组合起来当作主键,并且去掉重复的关系。你可以试着给 association_table 添加一个自动增长的主键看看效果如何。

撰写回答