2016-01-03 6 views
5

Próbuję utworzyć bazę danych w SQLite, która ma dwie tabele, jedną dla listy lotnisk, a drugą dla listy połączeń między parami tych lotnisk. Mam go skonfigurować jako samodzielny więzy, wiele do wielu relacji:Koncentracja kolby SQLAlchemy NOT NULL nie powiodła się na kluczu podstawowym

class Trips(db.Model): 

    __tablename__ = 'trips' 

    id = db.Column(db.Integer, primary_key=True) 
    airport_from = db.Column(db.Integer, db.ForeignKey('airport.id')) 
    airport_to = db.Column(db.Integer, db.ForeignKey('airport.id')) 
    price = db.Column(db.Float) 
    date = db.Column(db.Date) 

class Airport(db.Model): 

    __tablename__ = 'airport' 

    id = db.Column(db.Integer, primary_key=True) 
    iata = db.Column(db.String(8), index=True, unique=True) 
    name = db.Column(db.String(120), index=True, unique=True) 
    city = db.Column(db.String(120)) 
    region = db.Column(db.String(120)) 
    country = db.Column(db.String(120)) 

    flying_from = db.relationship('Trips', backref='end', primaryjoin=(id==Trips.airport_to)) 
    flying_to = db.relationship('Trips', backref='start', primaryjoin=(id==Trips.airport_from)) 

    def __repr__(self): 
     return '<Airport: {0}; IATA: {1}>'.format(self.name, self.iata) 

Kiedy otwieram moją skorupę Python i importować te modele, mam sesję sqlalchemy dodawać obiekty lotniskowe i zobowiązać się dobrze , ale gdy robię coś takiego:

>>> t = models.Trips(airport_from=3, airport_to=4, price=230.0) 
>>> db.session.add(t) 
>>> db.session.commit() 

daje mi to traceback:

Traceback (most recent call last): 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context 
context) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/engine/default.py", line 450, in do_execute 
cursor.execute(statement, parameters) 
sqlite3.IntegrityError: NOT NULL constraint failed: trips.id 

powyższy wyjątek był bezpośrednią przyczyną następującym wyjątkiem:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/scoping.py", line 150, in do 
    return getattr(self.registry(), name)(*args, **kwargs) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 813, in commit 
    self.transaction.commit() 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 392, in commit 
    self._prepare_impl() 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 372, in _prepare_impl 
    self.session.flush() 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2027, in flush 
    self._flush(objects) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2145, in _flush 
    transaction.rollback(_capture_exception=True) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__ 
    compat.reraise(exc_type, exc_value, exc_tb) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 183, in reraise 
    raise value 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2109, in _flush 
    flush_context.execute() 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/unitofwork.py", line 373, in execute 
    rec.execute(self) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/unitofwork.py", line 532, in execute 
    uow 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py", line 174, in save_obj 
    mapper, table, insert) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py", line 800, in _emit_insert_statements 
    execute(statement, params) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 914, in execute 
    return meth(self, multiparams, params) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection 
    return connection._execute_clauseelement(self, multiparams, params) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement 
    compiled_sql, distilled_params 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context 
    context) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception 
    exc_info 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 189, in raise_from_cause 
    reraise(type(exception), exception, tb=exc_tb, cause=exc_value) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 182, in reraise 
    raise value.with_traceback(tb) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context 
    context) 
    File "/Users/heli/nomad/flask/lib/python3.4/site-packages/sqlalchemy/engine/default.py", line 450, in do_execute 
    cursor.execute(statement, parameters) 
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: trips.id [SQL: 'INSERT INTO trips (airport_from, airport_to, price, date) VALUES (?, ?, ?, ?)'] [parameters: (3, 4, 230.0, None)] 

Kluczowym elementem wydaje się być dolna linia:

sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: trips.id [SQL: 'INSERT INTO trips (airport_from, airport_to, price, date) VALUES (?, ?, ?, ?)'] [parameters: (3, 4, 230.0, None)] 

Wygląda na to, bo nie dają wartość parametru id, że to odmowę dodać obiekt. Ale myślałem, że ten identyfikator zostanie automatycznie dodany i zwiększony, tak jak to miało miejsce w przypadku parametru obiektu obiektów Airport. Czego tu mi brakuje?

Odpowiedz

7

Dodaj wyraźny autoincrement=True Trips definicję klasy:

id = db.Column(db.Integer, primary_key=True, autoincrement=True) 

Jeśli tabela jest tworzona bez wyraźnej autoIncrement, trzeba zdać Trips.id = NULL w celu jej przyrostowych, patrz https://www.sqlite.org/faq.html#q1

+2

Dzięki D, to działało! Masz pojęcie, dlaczego muszę to robić w przypadku wycieczek, ale nie w przypadku dodawania obiektu lotniska? To znaczy. gdy utworzę obiekt Airport bez jawnego identyfikatora, mogę go dodać i zatwierdzić sesję bez żadnych problemów. – HLH

+0

Dobre pytanie, He) Czy możliwe jest, że mijasz Airport.id = NULL, gdy tworzysz nowy obiekt lotniskowy lub tabela Airport jest już zdefiniowana w SQLite z atrybutem AUTOINCREMENT? – MOCKBA

+1

Sprawdziłem dwukrotnie i nie zrobiłem nic, chociaż mogłem się mylić. Nie jest to jednak duży problem, o ile wszystko działa – HLH

Powiązane problemy