Używam piramidy z Sqlalchemy, Pyramid_TM i PostgreSQL, aby to przetestować.

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()


class MyList(Base):
    id = Column(Integer, primary_key=True)
    lst = Column(JSON)

Używam PostgreSQL 9.3+ i używając typu JSON. Kiedy to robię

mylst = MyList(lst=[])

Widzę również pustą listę [] w bazie danych, a także

def view(request):
    mylst = DBSession.query(MyList).get(1)
    mylst.lst.append('45')
    print(DBSession.is_active, DBSession.is_modified(mylst))

Widzę ['45'] w bazie danych i wydrukuj zwroty

True, True

Kontynuacja z góry [Edytuj] na następnym wniosku (powyżej jest już zaangażowany)

def view(request):
    mylst = DBSession.query(MyList).get(1)
    mylst.lst.append('65')
    print(DBSession.is_active, DBSession.is_modified(mylst))

DB nie zostanie zaktualizowany, nadal jest ['45'] i drukować zwroty

True, False

Czy robię coś złego lub jest to błąd?

8
idwaker 14 sierpień 2014, 09:05

3 odpowiedzi

Najlepsza odpowiedź

Domyślnie SQLalchemy trasa tylko zmiany samej wartości, która działa "zgodnie z oczekiwaniami" dla prostych wartości, takich jak INTS i Struny:

alice.name = "Alice"
alice.age = 8

Działa również, gdy przypisujesz nową wartość do kolumny "typu złożonego", takiego jak dykt lub lista:

alice.toys = ['doll', 'teddy bear']

Jednak SQLalchemy nie zauważa zmiany, jeśli zmodyfikujesz jeden z elementów na liście, lub dołącz / usuń wartość:

alice.toys[0] = 'teapot'
alice.toys.append('lego bricks')

Aby wykonać tę pracę, możesz mieć pewność, że przydzielisz nową listę za każdym razem:

toys = alice.toys[:]  # makes a "clone" of the existing list
toys[0] = 'teapot'
toys.append('lego bricks')
alice.toys = toys

Lub masz czytanie Śledzenie mutacji Rozdział w Dokumentach SQLalchemy Aby zobaczyć, jak możesz podklasować listę lub dyktować, aby śledzić modyfikacje swoich elementów.

Ponadto, ponieważ wspomniałeś, że używasz Postgres - jest dedykowany ARRAY Typ Postgres, którego można użyć zamiast JSON, jeśli wszystko, czego potrzebujesz, to przechowywać listy. Jednakże, co powiedziano powyżej o śledzeniu mutacji dotyczy też kolumn typu ARRAY również.

13
Antti Haapala 13 kwiecień 2019, 05:20

Możesz ręcznie oznaczać instancję jako zmodyfikowaną

from sqlalchemy.orm.attributes import flag_modified

def view(session):
    mylst = Session.query(MyList).get(1)
    mylst.lst.append('45')
    flag_modified(mylst, 'lst') # flag its `lst' attribute is modified
    print(Session.is_active, Session.is_modified(mylst))
    # (True, True)
2
neuront 28 październik 2016, 07:46

Spróbuj DBSession.flush() po mylst.lst.append('45'). Umożliwia to zaktualizowanie DB przed Pyramid_TM wykonującą zatwierdzenie.

Więcej informacji można znaleźć tutaj: http://docs.sqlalchemy.org/ PL / Najnowsze / ORM / Session.html # Flushing

-2
Raj 14 sierpień 2014, 06:26