【问题标题】:Flask SQLAlchemy duplicates烧瓶 SQLAlchemy 重复
【发布时间】:2021-03-18 20:39:41
【问题描述】:

我对这个问题不太了解,正在尝试找出如何消除表格中的重复项。

我使用 sqlite ( app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{DATABASE_PATH}" )

我有一张快递员表和一张快递员工作区域表。 我还有一个表格,可以链接快递员 ID 和地区 ID。

这里有一些代码:

couriers_regions_relationship = db.Table(
    "couriers_regions",
    db.Column("courier_id", db.Integer, db.ForeignKey("couriers.id")),
    db.Column("region_id", db.Integer, db.ForeignKey("regions.id")),
)
class Couriers(db.Model):
    __tablename__ = "couriers"
    id = db.Column(db.Integer, primary_key=True)
    regions = db.relationship("Regions", secondary=couriers_regions_relationship, lazy='dynamic')
    ...

class Regions(db.Model):
    __tablename__ = "regions"
    id = db.Column(db.Integer, primary_key=True)
    region = db.Column(db.Integer)
    ...

当我像这样创建一个表并向其中添加快递员时:

regions = [123, 77, 103]

new_courier = Couriers()
for region in regions:
    new_courier.regions.append(Regions(region=region))
db.session.add(new_courier)
db.session.commit()
...
regions = [123, 77, 103]
other_courier = Couriers()
for region in regions:
    other_courier.regions.append(Regions(region=region))
db.session.add(new_courier)
db.session.commit()
...

我得到以下表格:

couriers:
id | ...
---|-----
1  | ...
2  | ...

regions:
id | region | ...
---|--------|-----
1  | 123    | ...
2  | 77     | ...
3  | 103    | ...
4  | 123    | ...
5  | 77     | ...
6  | 103    | ...

couriers_regions:
courier_id | region_id
-----------|-----------
1          | 1
1          | 2
1          | 3
2          | 4 
2          | 5 
2          | 6

如您所见,“地区”表中的数据是重复的。

我想得到什么:

couriers:
id | ...
---|-----
1  | ...
2  | ...

regions:
id | region | ...
---|--------|-----
1  | 123    | ...
2  | 77     | ...
3  | 103    | ...

couriers_regions:
courier_id | region_id
-----------|-----------
1          | 1
1          | 2
1          | 3
2          | 1 
2          | 2 
2          | 3

我阅读了 sqlalchemy 文档和 flask_sqlalchemy 文档中的关系文档。在那里找不到任何关于它的信息。 我还尝试设置标志“unique=True”和“primary_key=True”,但没有帮助。

附言

  • 重复区域完全相同
  • 当然,我可以自己查看表格并搜索或创建我需要的区域、链接,但我想找到更优雅的解决方案

【问题讨论】:

    标签: python sqlalchemy flask-sqlalchemy


    【解决方案1】:

    每当您创建 Region 的新实例时,如果可能,它将被赋予一个新的数据库标识。

    两者都在这里:

    for region in regions:
        new_courier.regions.append(Regions(region=region))
    

    这里:

    for region in regions:
        other_courier.regions.append(Regions(region=region))
    

    ...您正在构建 Region 实例:Region(region=region)

    相反,构造Region 实例的集合,然后将它们分配给Courier 实例:

    regions = [Region(region=r) for r in [123, 77, 103]]
    

    然后:

    new_courier = Couriers(regions=regions)
    other_courier = Couriers(regions=regions)
    

    此外,数据库提供了一些工具来防止您试图避免的那种数据损坏。

    您可以通过在列上创建唯一索引来强制 Regions.region 始终是唯一的:

    class Regions(db.Model):
        ...
        region = db.Column(db.Integer, unique=True)
    

    或者,鉴于区域编号本身是一个唯一整数,您可以将其设为主键:

    class Region:
        # You could still call this column `region` but `Region.region` is redundant naming, `Region.id` sounds better to me!
        id = db.Column(db.Integer, primary_key=True, autoincrement=False)
    
    regions = [Region(id=r) for r in [123, 77, 103]]
    

    通过在数据库层强制区域的唯一性,它可以防止您编写错误的代码,从而无意中创建重复的区域记录。

    【讨论】:

    • 问题是区域不能存储在单个python变量中。另外,如果出现区域为 [123, 77, 99] 的 courier,则只需将区域 99 添加到区域表中,并自动创建与所有区域的关系
    • 在第二点上,您将首先对现有区域发出查询,例如,db.session.query(Regions).all(),将为您提供区域 127、77 和表中已存在的任何其他区域的对象.然后,您只需为 99 创建一个新区域。我不确定“区域不能存储在单个 python 变量中”是什么意思。恐怕如果您没有在问题中包含所有必要信息,您将得到不完全满足您需求的答案。
    • 不管怎样,关键是如果你想避免在你的表中有重复,你首先不允许它们,我的回答为你证明了。
    • 嗯嗯,谢谢,就是每次添加一个新的region,我检查表中是否存在,如果存在就取,否则就新建一个
    猜你喜欢
    • 2012-12-29
    • 2014-07-20
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 2019-01-04
    • 2018-04-02
    • 2019-01-12
    相关资源
    最近更新 更多