Flask SQLAlchemy 多对多插入重复条目

Posted

技术标签:

【中文标题】Flask SQLAlchemy 多对多插入重复条目【英文标题】:Flask SQLAlchemy Many To Many Insert Duplicates Entries 【发布时间】:2016-03-08 06:33:14 【问题描述】:

我创建了一个 Flask-SQLAlchemy API,其中包含项与标签的多对多关系。

一个简单的添加没有问题(在适当的表中插入项目和标签),但如果我添加另一个具有相同标签名称的项目,它会创建一组重复的标签名称,而不是仅仅将关联表链接到现有标签入口。

我发现一些情况与我的要求非常接近,但并不完全相同,我真的很难理解实现这一目标的最佳方法。

Prevent duplicate table entries in a many-to-many relationship in SQLAlchemy Many-to-many in sqlalchemy. Preventing SQLAlchemy from inserting into a table if a tag already exists

所以问题是:在标签表中只有唯一条目同时仍将标签与项目表正确关联的最佳方法是什么?

感谢您的任何帮助/指导!

这是我的模型:

items_tags = db.Table('items_tags',
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
    db.Column('item_id', db.Integer, db.ForeignKey('item.id'))
)

class Item(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(80), unique=False)
    code = db.Column(db.String(), unique=False)
    notes = db.Column(db.String(), unique=False)

    tags = db.relationship('Tag', secondary=items_tags, back_populates="items")

    def json(self):
        list_tag = []
        for tag in self.tags:
            list_tag.append("tag": tag.name, "id": tag.id )
        return json.loads(json.dumps("id": self.id, "title": self.title, "code": self.code, "notes": self.notes, "tags" : list_tag ))

    def __init__(self, title, code, notes, tags):
        self.title = title
        self.code = code
        self.notes = notes        
        self.tags = tags

    def __repr__(self):
        return self.title

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))

    items = db.relationship('Item', secondary=items_tags, back_populates="tags")

    def json(self):
        return 'id': self.id, 'tag': self.name

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

    def __repr__(self):
        return self.name

这里是控制器:

# curl -k -H "Content-Type: application/json" -X POST https://x.x.x.x/api/v1.0/items/ -d '"title": "title03", "code": "code03", "notes": "notes03", "tags": ["tag": "tag01", "tag": "tag02"]'
@app.route('/api/v1.0/items/', methods=['GET', 'POST'])
def items():
    if request.method == 'GET':
        return jsonify("items": [item.json() for item in Item.query.all()])

    if request.method == 'POST':
        if 'tags' in request.json:
            tags = request.json['tags']    
            for tag in tags:
              list_tags = [Tag(tag['tag']) for tag in tags]

        item = Item(request.json['title'], request.json['code'], request.json['notes'], list_tags)
        db.session.merge(item)
        db.session.commit()
        return jsonify(), 201

【问题讨论】:

您在自己的理解中创建新标签。如果您不想重复,则需要更改加载现有记录的方式 @dirn 我想这就是我卡住的地方。创建 Item 对象时,我不必提供 Tag 对象的列表吗?如果我更改列表推导以在 Tag 表中查找现有对象,我不会失去关联表中的关系吗? 您只会丢失与未包含在列表中的标签的关联。 【参考方案1】:

我错过了我需要查询标签是否首先存在的事实(@dirn 的意思是“改变你如何加载现有记录”)。

这是我为确保不添加重复标签所做的操作:

if request.method == 'POST':
    if 'tags' in request.json:
        list_tags = []
        for tag in request.json['tags']:
            if Tag.query.filter_by(name=tag['tag']).first():
                list_tags.append(Tag.query.filter_by(name=tag['tag']).first())
            else:
                list_tags.append(Tag(tag['tag']))

    item = Item(request.json['title'], request.json['code'], request.json['notes'], list_tags)
    db.session.merge(item)
    db.session.commit()
    return jsonify(), 201

【讨论】:

谢谢。这有助于我理解我的问题!

以上是关于Flask SQLAlchemy 多对多插入重复条目的主要内容,如果未能解决你的问题,请参考以下文章

Flask-SQLAlchemy 多对多插入

Flask Marshmallow/SqlAlchemy:序列化多对多关系

Flask SQLAlchemy 多对多关联对象错误

SqlAlchemy 和 Flask,如何查询多对多关系

python中flask和sqlalchemy的多对多

Flask/SQLAlchemy - 多对多关系的关联模型和关联表之间的区别?