SQLAlchemy: Zuordnungstabelle verwalten

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Benutzeravatar
Sophus
User
Beiträge: 1092
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Dienstag 31. Juli 2018, 21:42

Hallo Leute, ich habe euch ein ausführbares Programm mitgebracht. Worum geht es? Im nachfolgenden Beispiel seht ihr, dass ich eine Reihe von Filmen und Genre anlege. Soweit so gut. Im Abschnitt der Zuordnungstabelle (Allocation) weise ich dem Film "Saw" mehrere Genre zu. Mit Absicht habe ich dem Film den Genre "Comedy" zugeordnet. Wir alle wissen aber, dass Saw alles andere als Komödie ist. Nun will ich diesen Fehler beheben. Ich möchte aber nicht die Filme und/oder Genre aus den anderen Tabellen löschen. Noch möchte ich die anderen Konstellerationen löschen. Das heißt, "PSycho" und "Horror" sollen bleiben. Ich frage mich nun, was ich machen soll. Was mich nur verwirrt, ist, dass ich hier mit einer Verknüpfungstabelle arbeite. Bei einer einzelnen Tabelle bzw. bei einer 1:n-Beziehung hätte ich eher eine Lösung. Kann mir jemand mal weiterhelfen?

Damit ihr die Situation etwas besser versteht, habe ich Kommentare eingefügt.

Code: Alles auswählen

import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship, backref

sqlite_url = 'sqlite:///test.sqlite'

engine = sqlalchemy.create_engine(sqlite_url, echo = True)

Base = declarative_base()


class Allocation_Film_Genre(Base):
  __tablename__ = 'allocation_film_genre'
  genre_id = Column(Integer, ForeignKey('genre.id'), primary_key=True)
  film_id = Column(Integer, ForeignKey('film.id'), primary_key=True)

  genre = relationship("Genre", backref=backref("allocation_film_genre", lazy='dynamic', cascade="all, delete-orphan" ))
  film = relationship("Film", backref=backref("allocation_film_genre", lazy='dynamic', cascade="all, delete-orphan" ))

class Film(Base):
  __tablename__ = 'film'
  id = Column(Integer,  primary_key=True, unique=True)
  name = Column(String(80))

class Genre(Base):
  __tablename__ = 'genre'
  id = Column(Integer,  primary_key=True, unique=True)
  name = Column(String(80))

# Let us create all tables with certain columns
Base.metadata.create_all(engine)

# Now we have to create a session to work with.
Session = sessionmaker(bind=engine)
session = Session()

# We want to save some movies
film1 = Film(name="Saw")
film2 = Film(name="Amageddon")
film3 = Film(name="Little Stuart")
film4 = Film(name="Doom Day")

session.add_all([film1, film2, film3, film4])
session.commit()

# By the way we also want to save some genres 
genre1 = Genre( name = "Horror")
genre2 = Genre( name = "Comedy")
genre3 = Genre( name = "Psycho")
genre4 = Genre( name = "Thriller")

session.add_all([genre1, genre2, genre3, genre4])
session.commit()

# Hold on, we know we created an allocation table, because
# one movie can contains one or more genre, otherwise, one genre
# also can contains one or more movie, right? Let take us a look.
# For simulate we use the movie named 'Saw".
film_obj1 = session.query(Film).filter(Film.name=="Saw").one()
genre_obj1 = session.query(Genre).filter(Genre.name=="Horror").one()

film_obj2 = session.query(Film).filter(Film.name=="Saw").one()
genre_obj2 = session.query(Genre).filter(Genre.name=="Psycho").one()

film_obj3 = session.query(Film).filter(Film.name=="Saw").one()
genre_obj3 = session.query(Genre).filter(Genre.name=="Comedy").one()

allocation1 = Allocation_Film_Genre(film=film_obj1, genre=genre_obj1)
allocation2 = Allocation_Film_Genre(film=film_obj2, genre=genre_obj2)
allocation3 = Allocation_Film_Genre(film=film_obj3, genre=genre_obj3)

session.add_all([allocation1, allocation2, allocation3])
session.commit()

# Ok, we are done. All movies and genre are saved, and we also saved all
# allocation records. But wait! There is a mistake. Saw isn't a comedy. Damn!
# Shame on me!

# And now, I don't know what I have to do.
Antworten