Ar SQLAlchemy turi Django get_or_create atitikmenį?

Noriu gauti objektą iš duomenų bazės, jei ji jau egzistuoja (remiantis pateiktais parametrais) arba sukurti, jei ne.

Django get_or_create (arba šaltinis ) tai. Ar yra lygiavertė nuoroda į „SQLAlchemy“?

Šiuo metu rašau tai aiškiai:

 def get_or_create_instrument(session, serial_number): instrument = session.query(Instrument).filter_by(serial_number=serial_number).first() if instrument: return instrument else: instrument = Instrument(serial_number) session.add(instrument) return instrument 
109
30 марта '10 в 17:57 2010-03-30 17:57 „ FogleBird“ nustatė kovo 30 d. 10 val. 17:57 2010-03-30 17:57
@ 8 atsakymai

Tai iš esmės yra būdas tai padaryti, nėra nuorodos, lengvai prieinamos AFAIK.

Galite apibendrinti:

 def get_or_create(session, model, defaults=None, **kwargs): instance = session.query(model).filter_by(**kwargs).first() if instance: return instance, False else: params = dict((k, v) for k, v in kwargs.iteritems() if not isinstance(v, ClauseElement)) params.update(defaults or {}) instance = model(**params) session.add(instance) return instance, True 
66
06 апр. atsakymas pateikiamas 06 m. balandžio mėn. 2010-04-06 20:47 '10, 20:47, 2010-04-06 20:47

Po @WoLpH sprendimo šis kodas veikė (paprastas variantas):

 def get_or_create(session, model, **kwargs): instance = session.query(model).filter_by(**kwargs).first() if instance: return instance else: instance = model(**kwargs) session.add(instance) session.commit() return instance 

Tai galiu gauti bet kokį savo modelio objektą.

Tarkime, mano modelio objektas yra:

 class Country(Base): __tablename__ = 'countries' id = Column(Integer, primary_key=True) name = Column(String, unique=True) 

Jei norite sukurti arba sukurti savo objektą, rašau:

 myCountry = get_or_create(session, Country, name=countryName) 
73
Atsakymą pateikė Kevinas. 2011-05-21 01:08 Gegužės 21 d. 11 val. 1:08 2011-05-21 01:08

Aš žaidžiau su šia problema ir gavau gana patikimą sprendimą:

gana išsamią dienoraščio įrašą apie visas detales, bet keletą gana priežasčių, kodėl aš jį naudoju. 

  • Jis išpakuojamas į paketą, kuris nurodo, ar objektas egzistuoja, ar ne. Tai dažnai gali būti naudinga jūsų darbo eigoje.

  • Ši funkcija suteikia jums galimybę dirbti su @classmethod dekoruotomis kūrėjo funkcijomis (ir jiems būdingais atributais).

  • Sprendimas apsaugo nuo rasės sąlygų, kai turite daug procesų, susijusių su duomenų saugykla.

Redaguoti: session.commit() į session.flush() kaip aprašyta šiame dienoraščio įraše . Atkreipkite dėmesį, kad šie sprendimai būdingi naudojamam duomenų saugojimui (šiuo atveju Postgres).

2-asis redagavimas: atnaujintas naudojant {} kaip numatytąjį funkcijos funkciją, nes tai yra tipiškas „Python“. Ačiū už komentarą , Nigel! Jei jus domina tai, skaitykite ngn-wiki.ru.site/questions/15466 / ... ir šį dienoraščio įrašą .

34
15 янв. atsakymą pateikė erik Jan 15 2014-01-15 22:30 '14, 10.30 val. 2014-01-15 22:30

Modifikuota erik versija puikiai atsako

 def get_one_or_create(session, model, create_method='', create_method_kwargs=None, **kwargs): try: return session.query(model).filter_by(**kwargs).one(), True except NoResultFound: kwargs.update(create_method_kwargs or {}) try: with session.begin_nested(): created = getattr(model, create_method, model)(**kwargs) session.add(created) return created, False except IntegrityError: return session.query(model).filter_by(**kwargs).one(), True 
  • Naudokite įdėtą sandorį, jei norite grąžinti naują elementą tik vietoj visko atgal (žr. Šį atsakymą, kaip naudoti įdėtus sandorius su „SQLite“)
  • Perkelti create_method . Jei sukurtas objektas turi ryšį, o nariai per šį ryšį priskiriami, jis automatiškai įtraukiamas į sesiją. Pavyzdžiui. sukurkite book , kurioje atitinkamas ryšys yra user_id ir user , o tada book.user=<user object> viduje create_method pridės book į sesiją. Tai reiškia, kad create_method turi būti viduje, kad galėtumėte pasinaudoti galimu panaikinimu. Atminkite, kad „ begin_nested automatiškai paleidžia blykstę.

Atkreipkite dėmesį, kad naudojant „MySQL“, sandorio izoliavimo lygis turi būti nustatytas į READ COMMITTED , o ne REPEATABLE READ kad tai veiktų. Django get_or_create (ir čia ) naudoja tą pačią sluoksnį, taip pat žr. Django dokumentaciją .

6
24 мая '16 в 19:37 2016-05-24 19:37 atsakymą pateikė „ Adversus“ gegužės 24, 16 d. 19:37 2016-05-24 19:37

Manau, tik ieškojau to paties dalyko. Šis SQLALchemy receptas daro darbą maloni ir elegantiška.

6
01 июня '13 в 15:20 2013-06-01 15:20 atsakymas duotas jnwskas birželio 1 d. 13, 15:20 2013-06-01 15:20

Labiausiai tikėtina, kad tai yra semantiškai įmanoma:

 def get_or_create(model, **kwargs): """SqlAlchemy implementation of Django get_or_create. """ session = Session() instance = session.query(model).filter_by(**kwargs).first() if instance: return instance, False else: instance = model(**kwargs) session.add(instance) session.commit() return instance, True 

Nesu tikras, kaip kosheras pasikliauti pasauliniu mastu apibrėžta Sqlalchemy Session , bet Django versija nepriima ryšio, todėl ...

Grąžinama pakete yra egzempliorius ir logotipas, rodantis, ar egzempliorius buvo sukurtas (t. Y. Jis yra klaidingas, jei skaitome egzempliorių iš db).

Django get_or_create dažnai naudojamas, kad būtų prieinami pasauliniai duomenys, todėl perima kuo greičiau.

3
27 сент. atsakymas, kurį pateikė thebjorn Sep 27 2014-09-27 22:22 '14, 22:22 pm 2014-09-27 22:22

Aš šiek tiek supaprastinčiau @Kevin. venkite visos funkcijos įvyniojimo į „ if / else . Taigi, yra tik vienas return , kurį aš rasiu daugiau:

 def get_or_create(session, model, **kwargs): instance = session.query(model).filter_by(**kwargs).first() if not instance: instance = model(**kwargs) session.add(instance) return instance 
1
01 дек. atsakymas duotas jmberros 01 Dec. 2016-12-01 18:33 '16 at 18:33 2016-12-01 18:33

Priklausomai nuo jūsų atlikto izoliacijos lygio, nė vienas iš pirmiau minėtų sprendimų neveiks. Geriausias sprendimas, kurį radau, yra RAW SQL tokia forma:

 INSERT INTO table(f1, f2, unique_f3) SELECT 'v1', 'v2', 'v3' WHERE NOT EXISTS (SELECT 1 FROM table WHERE f3 = 'v3') 

Jis yra saugus sandoriams, nepriklausomai nuo izoliacijos lygio ir lygiagretumo laipsnio.

Saugokitės, kad būtų veiksminga, būtų protinga turėti unikalų stulpelį INDEX.

1
20 февр. Atsakymas pateikiamas fcracker79 20 vasario mėn. 2016-02-20 19:16 '16 at 19:16 2016-02-20 19:16