【问题标题】:Update many to many association table with derived field使用派生字段更新多对多关联表
【发布时间】:2015-09-03 13:07:25
【问题描述】:

我正在使用 Flask、Flask-SQLalchemy 和 Flask-Restful 编写一个 RESTful API。我有联系人和类别的模型,以及用于映射它们之间的多对多关系的帮助表。

contactgrouping = db.Table('CONTACT_GROUPING',
    db.Column('catid', db.Integer, db.ForeignKey('CATEGORY.catid')),
    db.Column('contactid', db.Integer, db.ForeignKey('CONTACT.contactid')),
    db.Column('clientid', db.Integer, db.ForeignKey('CLIENT.clientid')),
)

class Contact(db.Model):

    __tablename__ = 'CONTACT'
    contactid = db.Column(db.Integer, primary_key=True)
    clientid = db.Column(db.Integer, db.ForeignKey('CLIENT.clientid'))
    firstname = db.Column(db.String(50))
    lastname = db.Column(db.String(50))
    categories = db.relationship('Category',secondary = contactgrouping, backref='contact', lazy='dynamic')

class Category(db.Model):

    __tablename__ = 'CATEGORY'
    catid = db.Column(db.Integer, primary_key=True)
    clientid = db.Column(db.Integer, db.ForeignKey('CLIENT.clientid'))
    catname = db.Column(db.String(50))

我正在使用 ORM 更新给定联系人的类别,这运行良好。复杂之处在于映射表有一个非规范化字段clientid,它与联系人表中的clientid 相同。当 ORM 更新联系人的类别分配时,我需要填充此字段,但它仅插入 contactidcatid 列。

例子:

            category = Category.query.get(catid).first()
            if (category is not None):
                contact.categories.append(category)

这会生成 SQL:

INSERT INTO `CONTACT_GROUPING` (catid, contactid) VALUES (%s, %s)

当我真的需要它时:

INSERT INTO `CONTACT_GROUPING` (catid, contactid, clientid) VALUES (%s, %s, %s)

如何定义联系人和类别之间的关系,以便此派生字段也通过 ORM 填充?

【问题讨论】:

    标签: python flask sqlalchemy many-to-many flask-sqlalchemy


    【解决方案1】:

    我从https://twitter.com/140am 那里得到了一些帮助。我需要将contactgrouping 表示为模型而不是表,以便我可以直接使用关系和访问字段。

    class Category(db.Model):
    
        resource_fields = {
            'id': fields.Integer(attribute='catid'),
            'name': fields.String(attribute='catname')
        }
    
        __tablename__ = 'CATEGORY'
        catid = db.Column(db.Integer, primary_key=True)
        clientid = db.Column(db.Integer, db.ForeignKey('CLIENT.clientid'))
        catname = db.Column(db.String(50))
    
        def __repr__(self):
            return '<Category %r>' % (self.catname)
    
    class ContactGrouping(db.Model):
    
        resource_fields = {
            'id': fields.Integer(attribute='catid'),
            'name': fields.String(attribute='category.catname'),
        }
    
        __tablename__ = 'CONTACT_GROUPING'
        __table_args__ = (
            PrimaryKeyConstraint('catid', 'contactid', 'clientid'),
        )
    
        catid = db.Column(db.Integer, db.ForeignKey('CATEGORY.catid'))
        contactid = db.Column(db.Integer, db.ForeignKey('CONTACT.contactid'))
        clientid= db.Column(db.Integer, db.ForeignKey('CONTACT.clientid'))
        category = db.relationship('Category')
    
        def __repr__(self):
            return '<ContactGrouping %r %r>' % (self.catid, self.contactid)
    
    class Contact(db.Model):
    
        resource_fields = {
            'id': fields.Integer(attribute='contactid'),
            'firstname': fields.String,
            'lastname': fields.String,
            'categories': fields.List(fields.Nested(ContactGrouping.resource_fields))
        }
    
        __tablename__ = 'CONTACT'
        contactid = db.Column(db.Integer, primary_key=True)
        clientid = db.Column(db.Integer, db.ForeignKey('CLIENT.clientid'))
        firstname = db.Column(db.String(50))
        lastname = db.Column(db.String(50))
        categories = db.relationship('ContactGrouping', backref='contact', lazy='dynamic', foreign_keys='ContactGrouping.contactid')
    
        def __repr__(self):
            return '<Contact %r %r>' % (self.firstname, self.lastname)
    

    并在视图中使用它:

            category = Category.query.get(catid).first()
            contactgrouping = ContactGrouping(contactid=id, catid=category.catid, clientid = contact.clientid)
            if (contactgrouping is not None):
                contact.categories.append(contactgrouping)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多