2012-07-25 12 views
7

Używam SQLAlchemy w projekcie, który nie jest aplikacją internetową. Jest to aplikacja serwerowa, która ładuje wiele różnych obiektów z bazy danych i modyfikuje je lokalnie, ale nie chce zapisywać tych aktualizacji w bazie danych za każdym razem, gdy zostanie wydane zatwierdzenie. Wcześniej współpracowałem z Django ORM przy niektórych projektach internetowych i stwierdziłem, że lepiej pasuje do tego, co próbuję osiągnąć. W Django ORM mogłem .save() każdy obiekt, kiedy tylko chciałem, bez zapisywania innych rzeczy, których może nie chcę zapisać. Rozumiem, dlaczego to działa w SQLAlchemy, ale zastanawiam się, jak mogłem to zrobić w sposób podobny do Django?Wyłączanie zatwierdzania zmian obiektu w SQLAlchemy


Aktualizacja: Aby łatwiej zrozumieć, co próbuję osiągnąć, będę zapewnić wam przykład.

Jak to działa w rzeczywistości:

a = MyModel.query.get(1) 
b = MyModel.query.get(1) 

a.somefield = 1 
b.somefield = 2 

# this will save both of changed models 
session.commit() 

ten sposób chcę go do pracy:

a = MyModel.query.get(1) 
b = MyModel.query.get(1) 

a.somefield = 1 
b.somefield = 2 

a.save() 
# I didn't want to save b, changes of b weren't committed 

Chcę mieć większą kontrolę tego, co jest rzeczywiście zapisane. Chcę zapisać zmiany każdego obiektu co 5 minut.

+0

Czy znalazłeś własne rozwiązanie? Jeśli tak, proszę, udostępnij. –

Odpowiedz

2

Używam czegoś takiego:

class BaseModel(object): 
    def save(self, commit=True): 
     # this part can be optimized. 
     try: 
      db.session.add(self) 
     except FlushError: 
      # In case of an update operation. 
      pass 

     if commit: 
      db.session.commit() 

    def delete(self, commit=True): 
     db.session.delete(self) 

     if commit: 
      db.session.commit() 

a potem określić moje modele jak:

class User(db.Model, BaseModel) 

Więc teraz mogę zrobić:

u = User(username='foo', password='bar') 
u.save() 

jest to, co planowaliśmy osiągnąć?

2

Nie jestem pewien, czy rozumiem twoje położenie.

W Django

foo = MyModel(field1='value1', field2='value2') 
foo.save() 

lub alternatywnie

foo = MyModel.objects.create(field1='value1', field2='value2') 

W SQLAlchemy,

foo = MyModel(field1='value1', field2='value2') 
session.add(foo) 

W tym momencie masz tylko dodania obiektu do sesji i nie ma jeszcze popełnił transakcję. Trzeba popełnić tylko po wykonaniu niezależnie od zmiany były wymagane

session.commit() 

przyjrzeć że ten link. Myślę, że ułatwi to przejście z Django ORM do SqlAlchemy.

UPDATE

Dla takiej sytuacji, można użyć wielu sesji.

engine = create_engine("postgresql+psycopg2://user:[email protected]/test") 
metadata = MetaData(bind=engine) 
Session = sessionmaker(bind=engine) 
session1 = Session() 
session2 = Session() 
Base = declarative_base() 
class User(Base): 
    __tablename__ = 'users' 
    id = Column(Integer, primary_key=True) 
    name = Column(String) 
    age = Column(Integer) 
    def __init__(self, name, age): 
     self.name = name 
     self.age = age 
    def __repr__(self): 
     return "<User('%s','%s')>" % (self.name, self.age) 
Base.metadata.create_all(engine) 

Utworzono tabelę "użytkownicy" w bazie danych "test". Ponadto zainicjowano 2 obiekty sesji, sesja 1 i sesja2.

a = User('foo','10') 
b = User('bar', '20') 
session1.add(a) 
session1.add(b) 
session1.commit() 

Użytkownikom tabela będzie teraz mieć 2 rekordy

1: foo, 10 
2: bar, 20 

pobierania 'foo' rekord śpiewać session1 i 'bar' używając session2.

foo = session1.query(User).filter(User.name == "foo").first() 
bar = session2.query(User).filter(User.name == "bar").first() 

wprowadzeniem zmian w 2 rekordy

foo.age = 11 
bar.age = 21 

Teraz, jeśli chcesz zmiany Foo sam na przeniesienie,

session1.commit() 

i do baru,

session2.commit() 
+0

Zmieniłem moje pytanie, aby wyjaśnić, co próbuję osiągnąć. – kjagiello

+0

Potrzebuję jednej sesji na każdy obiekt, który będę przechowywać w mojej aplikacji i wygląda na to, że w moim przypadku będzie to dość duże obciążenie. – kjagiello

0

Nie wzniecać stary post, ale

Mówisz:

chcę zapisać zmiany każdego obiektu co 5 minut lub więcej.

Więc dlaczego nie użyć planującego jak Celery (używam pyramid_celery)

Dzięki temu można zaoszczędzić każdego obiektu co 5 minut, czyli można dodać dekorator.

@periodic_task(run_every=crontab(minute="*/5") 
def somefunction(): 
    #your code here 

ten działa świetnie, zwłaszcza gdy musisz zaktualizować bazę danych, aby upewnić się, że jest aktualna (w przypadku, gdy wielu użytkowników używa Twojego systemu).

Mam nadzieję, że to pomoże komuś z, zapisywanie co 5 minut część.

Powiązane problemy