python - SQLAlchemy( flask )中的外键在插入数据库之前发生变化?

标签 python mysql database sqlalchemy flask

我正在尝试使用 SQLAlchemy 将一些记录插入到带有外键的数据库中,但外键似乎并没有像我预期的那样发生变化。

我在两个对象(账户和交易)之间有一个简单的 1-M 关系。帐户对象已很好地插入到数据库中,但是当我尝试遍历这些帐户并向它们添加交易对象时,所有交易的外键是被遍历的最后一个帐户的 ID。

谁能帮我弄清楚这是为什么?它一直让我发疯!

我的账户和交易对象:

class Account(db.Model):
    number = db.Column(db.String(80), primary_key=True)
    bsb = db.Column(db.String(80), primary_key=True)
    name = db.Column(db.String(80))
    description = db.Column(db.String(80))

class Transaction(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    account_id = db.Column(db.String(80), db.ForeignKey('account.number'))
    amount = db.Column(db.Float(precprecision=2))

这里是我遍历数据库中的账户并尝试向它们添加交易对象的地方:

def Sync_Transactions():
    #The following definately returns two account objects from the DB
    accounts = [db.session.query(Account).filter(Account.number == '999999999').first(), db.session.query(Account).filter(Account.number == '222222222').first()]

    for acc in accounts:
        #The following parses a CSV file for the account and returns transaction objecs as a list
        transactions = myLib.ParseCsvFile('C:\\transactions_%s.csv' % (acc.number))
        acc.transactions = transactions
        db.session.merge(acc)
    db.session.commit()

以上,如果从数据库中只检索到 1 个帐户,则工作正常。一旦我开始遍历多个账户,所有交易都会获得相同的外键(最后一个账户的 key - 在上述情况下为 222222222)

这里是问题所在

def ParseCsvFile(self, fileLocation, existingTransactionList=[]):
    with open(fileLocation, 'rb') as f:
        reader = csv.DictReader(f,['Date','TransactionAmount','C','D','TransactionType','TransactionDescription','Balance'])
        for row in reader:
            if not row['TransactionDescription'] == '':
                existingTransactionList.append(Transaction(
                    float(row['TransactionAmount'])
                    )
                )
    return existingTransactionList

由于某些原因,具有参数 existingTransactionList 会导致问题。如果我将上面的代码更改为以下代码,问题就会消失,但我仍然不明白为什么由于我缺乏 python 知识,我猜 :)

def ParseCsvFile(self, fileLocation, existingTransactionList=[]):
    existingTransactionList=[]
    with open(fileLocation, 'rb') as f:
        reader = csv.DictReader(f,['Date','TransactionAmount','C','D','TransactionType','TransactionDescription','Balance'])
        for row in reader:
            if not row['TransactionDescription'] == '':
                existingTransactionList.append(Transaction(
                    float(row['TransactionAmount'])
                    )
                )
    return existingTransactionList

我将 existingTransactionList 变量作为参数的原因是因为我最终想要传递现有交易的列表,并且只有唯一的交易会通过使用类似以下内容的方式返回:

transactionList = list(set(existingTransactionList))

最佳答案

问题是您要将所有 交易添加到最后一个帐户。变化:

def ParseCsvFile(self, fileLocation, existingTransactionList=[]):

def ParseCsvFile(self, fileLocation, existingTransactionList=None):
    if existingTransactionList is None:
        existingTransactionList = []

为什么会这样

Python 只解析函数的声明一次,所有默认参数都在这个编译阶段绑定(bind)到它们的值。这意味着不是每次调用 ParseCsvFile 都会得到一个新列表,而是每次调用 ParseCsvFile 都会使用相同列表。

要查看发生了什么,请在命令行中尝试以下操作:

def test_mutable_defaults(value, x=[], y={}):
    print("x's memory id this run is", id(x))
    print("Contents of x", x)
    print("y's memory id this run is", id(y))
    print("Contents of y", y)

    x.append(value)
    y[value] = value

    return x, y

然后使用这个函数:

test_mutable_defaults(1)
test_mutable_defaults(2)
test_mutable_defaults(3)

如果 Python 在每次调用时重新计算 xy,您会看到每次调用都有不同的内存 ID,而 x 将是 [1],然后是 [2],然后是 [3]。因为 Python 在第一次编译 test_mutable_defaults 时只评估 xy 你会看到 相同内存 ID >x 每次调用(对于 y 也是如此),x 将是 [1],然后是 [1 , 2] 然后是 [1, 2, 3]

关于python - SQLAlchemy( flask )中的外键在插入数据库之前发生变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21647282/

相关文章:

php - 最佳实践 : Tracking Banner Impressions

python - "fails to import module"在 Ubuntu 18.04 上运行 sphinxcontrib-matlabdomain 的 test_data 示例时

python-requests 等同于 curl 的 --data-binary?

mysql - 在 mysql 中使用 group by 生成计数数据

mysql - 在mysql查询结果中添加迄今为止的小时数

c# - 如何进行sql查询将数据库字符串分成3个不同的部分并比较它们?

php - mysql注入(inject)破坏?

python - 使用 "with"语句访问 Python 类方法

python - Django 表单验证包括 session 数据的使用

mysql - map 表的 Rails 范围