Integrity Error when trying to upload to MySQL DB in python

Pippa97 :

I have this code which currently lets me update a school's data in mySQL database, if the id already exists. However, what I am also trying to achieve, is that if the ID doesn't exist in the DB, it inserts those values. Here is the code I've got so far:

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)

This will update correctly, however, when I try to add a completely new school to the db, with this code:

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

I get this error:

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)

Does anyone know how to get rid of this error?

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' UPDATE '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

The above is working now. I am now trying to combine the add and update functions so that it checks if the id exists in the table. If not, it inserts a new row. If it does, then it just updates the values. Below is my code so far, thanks to @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

It is not producing any errors, but it's not adding or updating either. Can anyone see what I've done wrong?

TheSynt4x :

The error is perhaps with your constructor.

You have a class member that is: _id = db.Column('_id', db.Unicode, primary_key=True)

but in your constructor you're setting self.id = id

A fix for this problem would be to either update your model for the code to look like this:

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

or what someone in the comments suggested to do by adding a default value to your column. However, I would not suggest adding a default value to your primary key.

Another possible solution for this problem is to create an add_or_update method to your class, which is the better solution for the long run. You do it by adding a class method which gets a result by id, if it doesn't exist, your code will create one or update the existing retrieved result. This is how you would implement the following code:

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

Good luck and cheers!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=11828&siteId=1