PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Sqlalchemy:dodatkowa aktualizacja relacji

Problem polega na tym, że chcesz mieć pewność, że tworzone instancje są niepowtarzalne. Możemy stworzyć alternatywny konstruktor, który sprawdzi pamięć podręczną istniejących niezatwierdzonych instancji lub odpytuje bazę danych o istniejącą zatwierdzoną instancję przed zwróceniem nowej instancji.

Oto demonstracja takiej metody:

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 Metoda została zainspirowana przykładem z wiki SQLAlchemy . Ta wersja jest znacznie mniej zawiła, przedkłada prostotę nad elastyczność. Używałem go w systemach produkcyjnych bez żadnych problemów.

Są oczywiście ulepszenia, które można dodać; to tylko prosty przykład. get_unique metoda może być dziedziczona z UniqueMixin , do wykorzystania w dowolnej liczbie modeli. Można by wprowadzić bardziej elastyczne zapamiętywanie argumentów. Odkłada to również na bok problem wielu wątków wstawiających sprzeczne dane wspomniane przez Ants Aasma; obsługa, która jest bardziej złożona, ale powinna być oczywistym rozszerzeniem. Zostawiam to tobie.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL:ograniczenie, które wpływa na wiele tabel

  2. Indeks Postgresql na wyrażeniu xpath nie przyspiesza

  3. Nie można połączyć się z Postgres DB, ponieważ typ uwierzytelniania 10 nie jest obsługiwany

  4. Rozmyte dopasowanie ciągu w SQL

  5. Jak uzyskać zwracany identyfikator w JPA po wstawieniu natywnego zapytania?