sql >> Databasteknik >  >> RDS >> PostgreSQL

Sqlalchemy:sekundär relationsuppdatering

Problemet är att du vill se till att instanserna du skapar är unika. Vi kan skapa en alternativ konstruktor som kontrollerar en cache för befintliga icke-kommitterade instanser eller frågar databasen efter befintliga commited-instanser innan vi returnerar en ny instans.

Här är en demonstration av en sådan metod:

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 inspirerad av exemplet från SQLAlchemy-wikin . Denna version är mycket mindre invecklad och gynnar enkelhet framför flexibilitet. Jag har använt det i produktionssystem utan problem.

Det finns uppenbarligen förbättringar som kan läggas till; detta är bara ett enkelt exempel. get_unique metod kan ärvas från en UniqueMixin , att användas för valfritt antal modeller. Mer flexibel memoisering av argument skulle kunna implementeras. Detta lägger också åt sidan problemet med flera trådar som infogar motstridiga data som nämns av Ants Aasma; hantering som är mer komplex men borde vara en självklar förlängning. Jag lämnar det till dig.



  1. Finns det någon MySQL Aggregate-funktion för CONTAINS?

  2. Hur ON CONFLICT fungerar i SQLite

  3. Kan flera trådar orsaka dubbletter av uppdateringar på begränsad uppsättning?

  4. Oracle DBMS_LOB.INSTR och CONTAINS prestanda