У меня есть этот код, который в настоящее время позволяет мне обновлять данные школы в базе данных MySQL, если идентификатор уже существует. Тем не менее, чего я также пытаюсь добиться, так это того, что если идентификатор не существует в БД, он вставляет эти значения. Вот код, который я получил до сих пор:

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost/dbName'
db = SQLAlchemy(app)

class Example(db.Model):
    __tablename__ = 'schools'
    _id = db.Column('_id', db.Unicode, primary_key=True)
    establishmentNumber = db.Column('establishmentNumber', db.Unicode)

    def __init__(self, id, establishmentNumber):
        self.id = id
        self.establishmentNumber = establishmentNumber

update_this = Example.query.filter_by(_id=school._id.iloc[0]).first()

update_this.establishmentNumber = 'bob'
db.session.commit()

examples = Example.query.all()
examples

for ex in examples:
    print (ex.establishmentNumber)

Тем не менее, это будет корректно обновляться, когда я попытаюсь добавить совершенно новую школу в БД с этим кодом:

new_ex = Example('5c12345scl', 'fifth')
db.session.add(new_ex)
db.session.commit()

Я получаю эту ошибку:

IntegrityError: (MySQLdb._exceptions.IntegrityError) (1364, "Field '_id' doesn't have a default value")
[SQL: INSERT INTO schools (`establishmentNumber`) VALUES (%s)]
[parameters: ('fifth',)]
(Background on this error at: http://sqlalche.me/e/gkpj)

Кто-нибудь знает, как избавиться от этой ошибки?

«» «» « » «» «» « » «» «» « » «» «» « » «» «» « » «» «» « » «» «» « » «» «» « » «» ''''''''' ОБНОВИТЬ '''''''''''''''''''''''''''''''''''''''' «» «» «» « » «» «» « » «» «»»

Выше работает сейчас. Сейчас я пытаюсь объединить функции добавления и обновления, чтобы он проверял, существует ли идентификатор в таблице. Если нет, то вставляется новая строка. Если это так, то он просто обновляет значения. Ниже приведен мой код, благодаря @James Summers:

class Example(db.Model):
    __tablename__ = 'schools'
    _id = db.Column('_id', db.Unicode, primary_key=True)
    establishmentNumber = db.Column('establishmentNumber', db.Unicode)
    laCode = db.Column('laCode', db.Unicode)
    urn = db.Column('urn', db.Unicode)
    name = db.Column('name', db.Unicode)
    phaseOfEducation = db.Column('phaseOfEducation', db.Unicode)
    wondeID = db.Column('wondeID', db.Unicode)

    def __init__(self, _id, establishmentNumber, laCode, urn, name, phaseOfEducation, wondeID):
        self._id = _id
        self.establishmentNumber = establishmentNumber
        self.laCode = laCode
        self.urn = urn
        self.name = name
        self.phaseOfEducation = phaseOfEducation
        self.wondeID = wondeID

        def add_or_update(self, _id, establishmentNumber, laCode, urn, name, phaseOfEducation, wondeID):
            update_this = Example.query.filter_by(_id=school._id.iloc[0]).first()

            if not update_this:
                new_ex = Example(school._id.iloc[0], school.establishmentNumber.iloc[0], school.laCode.iloc[0], school.urn.iloc[0], school.name.iloc[0], school.phaseOfEducation.iloc[0], school.wondeID.iloc[0])
                db.session.add(new_ex)
                db.session.commit()

            else:
                update_this.establishmentNumber = 'hello'
                db.session.commit()

            return new_ex

Он не производит никаких ошибок, но не добавляет и не обновляет. Кто-нибудь может увидеть, что я сделал не так?

1
Pippa97 20 Фев 2020 в 12:42

2 ответа

Лучший ответ

Возможно, ошибка в вашем конструкторе.

У вас есть ученик, который: _id = db.Column('_id', db.Unicode, primary_key=True)

Но в вашем конструкторе вы устанавливаете self.id = id

Решением этой проблемы было бы обновить вашу модель, чтобы код выглядел следующим образом:

class Example(db.Model):
    __tablename__ = 'schools'
    _id = db.Column('_id', db.Unicode, primary_key=True)
    establishmentNumber = db.Column('establishmentNumber', db.Unicode)

    def __init__(self, id, establishmentNumber):
        self._id = id
        self.establishmentNumber = establishmentNumber

Или что кто-то в комментариях предложил сделать, добавив значение по умолчанию в ваш столбец. Однако я бы не советовал добавлять значение по умолчанию к первичному ключу.

Другое возможное решение этой проблемы - создать метод add_or_update для вашего класса, который является лучшим решением в долгосрочной перспективе. Вы делаете это, добавляя метод класса, который получает результат по идентификатору, если он не существует, ваш код создаст его или обновит существующий полученный результат. Вот как бы вы реализовали следующий код:

class Example(db.Model):
    __tablename__ = 'schools'

    _id = db.Column('_id', db.Unicode, primary_key=True)
    establishmentNumber = db.Column('establishmentNumber', db.Unicode)

    def __init__(self, id, establishmentNumber):
        self._id = id
        self.establishmentNumber = establishmentNumber

    @classmethod
    def add_or_update(cls, example_id, establishmentNumber):
        entity = cls.query.filter_by(id=example_id).first()

        if not entity:
          entity = cls(example_id, establishmentNumber)

        entity.establishmentNumber = establishmentNumber

        db.session.add(entity)
        db.session.commit()

        return entity

Удачи и ура!

0
TheSynt4x 20 Фев 2020 в 10:46

Благодаря комментариям @ Акина. Я понял, что проблема была с кодом этой функции:

def __init__(self, id, establishmentNumber):
    self.id = id
    self.establishmentNumber = establishmentNumber

Я написал идентификатор без подчеркивания, так что это исправленная версия:

def __init__(self, _id, establishmentNumber):
    self._id = _id
    self.establishmentNumber = establishmentNumber
1
Pippa97 20 Фев 2020 в 10:30