sql >> Database teknologi >  >> RDS >> PostgreSQL

Sqlalchemy:sekundær forholdsopdatering

Problemet er, at du vil sikre dig, at de forekomster, du opretter, er unikke. Vi kan oprette en alternativ konstruktør, der kontrollerer en cache af eksisterende ukommiterede forekomster eller forespørger databasen for eksisterende forpligtede forekomster, før vi returnerer en ny forekomst.

Her er en demonstration af en sådan metode:

from sqlalchemy import Column, Integer, String, ForeignKey, Table
from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative.api import declarative_base
from sqlalchemy.orm import sessionmaker, relationship

engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(engine)
Base = declarative_base(engine)

session = Session()


class Role(Base):
    __tablename__ = 'role'

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False, unique=True)

    @classmethod
    def get_unique(cls, name):
        # get the session cache, creating it if necessary
        cache = session._unique_cache = getattr(session, '_unique_cache', {})
        # create a key for memoizing
        key = (cls, name)
        # check the cache first
        o = cache.get(key)
        if o is None:
            # check the database if it's not in the cache
            o = session.query(cls).filter_by(name=name).first()
            if o is None:
                # create a new one if it's not in the database
                o = cls(name=name)
                session.add(o)
            # update the cache
            cache[key] = o
        return o


Base.metadata.create_all()

# demonstrate cache check
r1 = Role.get_unique('admin')  # this is new
r2 = Role.get_unique('admin')  # from cache
session.commit()  # doesn't fail

# demonstrate database check
r1 = Role.get_unique('mod')  # this is new
session.commit()
session._unique_cache.clear()  # empty cache
r2 = Role.get_unique('mod')  # from database
session.commit()  # nop

# show final state
print session.query(Role).all()  # two unique instances from four create calls

create_unique metoden var inspireret af eksemplet fra SQLAlchemy-wikien . Denne version er meget mindre indviklet og favoriserer enkelhed frem for fleksibilitet. Jeg har brugt det i produktionssystemer uden problemer.

Der er naturligvis forbedringer, der kan tilføjes; dette er blot et simpelt eksempel. get_unique metode kunne arves fra en UniqueMixin , der skal bruges til et vilkårligt antal modeller. Mere fleksibel memorisering af argumenter kunne implementeres. Dette tilsidesætter også problemet med flere tråde, der indsætter modstridende data nævnt af Ants Aasma; håndtering, der er mere kompleks, men som burde være en oplagt udvidelse. Det overlader jeg til dig.



  1. Hvordan kan jeg lytte efter oprettelsen af ​​en specifik model og oprette en ny (på en anden tabel) baseret på dette?

  2. SQL Seneste billeder fra kontakter (grupperet efter kontakt)

  3. Django, der kombinerer AND og OR-forespørgsler med ManyToMany Field

  4. PostgreSQL træning for MySQLere