zope.generations suteikia atnaujinimo objektų duomenų bazėje, kaip tada, kai paraiška schemų pakeitimai, & nbsp;. Paraiškos schemą iš esmės yra duomenų struktūra, klasių struktūra į ZODB atveju arba stalo aprašymuose atveju reliacinės duomenų bazės.
Detali dokumentacija
Kartos yra atnaujinimo objektų duomenų bazėje, kai programa schemų keitimais būdas. Taikymo schemos iš esmės yra duomenų struktūra, klasių struktūra į ZODB ar stalo aprašymuose reliacinės duomenų bazės atveju.
Kai keičiate savo paraišką anketa duomenų struktūras, pavyzdžiui, galite pakeisti semantinę prasmę esamo srityje klasė, turėsite su duomenų bazėmis, kurios buvo sukurtos prieš jūsų kaitos problemą. Dėl išsamesnio svarstymo ir galimų sprendimų ieškokite http://wiki.zope.org/zope3/DatabaseGenerations
Mes bus naudojamas komponentas architektūra, ir mes turime duomenų bazę ir ryšį:
& Nbsp; >>> import cgi
& Nbsp; >>> iš pprint importo pprint
& Nbsp; >>> iš zope.interface importo padargai
& Nbsp; >>> iš ZODB.tests.util importo DB
& Nbsp; >>> db = BP ()
& Nbsp; >>> Conn = db.open ()
& Nbsp; >>> root = conn.root ()
Įsivaizduokite, kad mūsų prašymas yra orakulas: jūs galite išmokyti jį reaguoti į frazes. Leiskite laikyti jį paprasta ir laikykite dict duomenys:
& Nbsp; >>> šaknų [atsakymus '] = {"Labas": "?" Hi & kaip jums tai padaryti ",
& Nbsp; <...> "? Prasmė gyvenimo": "42",
& Nbsp; <...> "keturių ": "Keturių
& Nbsp; >>> transaction.commit ()
Pirminis nustatymas
Štai keletas kartų specifinis kodas. Mes sukursime ir registruoti SchemaManager. SchemaManagers yra atsakingi už faktinių atnaujinimuose duomenų bazę. Tai vienas bus tik manekenas. Taškas čia yra padaryti kartos modulis žinoti, kad mūsų programa palaiko kartas.
Numatytasis įgyvendinimas SchemaManager netinka šiam testui, nes jis naudoja Python modulių valdyti kartas. Nes dabar, tai bus tik bauda, nes nenorime, kad nieko daryti tik dar.
& Nbsp; >>> iš zope.generations.interfaces importuoti ISchemaManager
& Nbsp; >>> iš zope.generations.generations importuoti SchemaManager
& Nbsp; >>> import zope.component
& Nbsp; >>> dummy_manager = SchemaManager (minimum_generation = 0, karta = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... dummy_manager, ISchemaManager, vardas = 'some.app)
"Some.app" yra unikalus identifikatorius. Jūs turėtumėte naudoti URI ar punktyrine vardą savo paketą.
Paleidus Zope ir duomenų bazės yra atidarytas, renginys IDatabaseOpenedWithRoot siunčiamas. Zope registruoja evolveMinimumSubscriber pagal nutylėjimą kaip šio įvykio prižiūrėtojas. Leiskite imituoti tai:
& Nbsp; >>> klasės DatabaseOpenedEventStub (objektas):
& Nbsp; ... Def __init __ (self, duomenų bazė):
& Nbsp; ... self.database = duomenų bazė
& Nbsp; >>> įvykis = DatabaseOpenedEventStub (dB)
& Nbsp; >>> iš zope.generations.generations importuoti evolveMinimumSubscriber
& Nbsp; >>> evolveMinimumSubscriber (įvykis)
Šio veiksmo pasekmė yra tai, kad dabar duomenų bazėje yra tai, kad mūsų dabartinis schemos skaičius yra 0. Kai mes atnaujinti schemą, zope3 turės ką atspirties taškas buvo idėja. Čia matote?
& Nbsp; >>> iš zope.generations.generations importuoti generations_key
& Nbsp; >>> šaknis [generations_key] ['some.app']
& Nbsp; 0
Realiame gyvenime niekada neturėtų vargintis su šio rakto tiesiogiai, bet jūs turėtumėte žinoti, kad jis egzistuoja.
Atnaujinti scenarijus
Atgal į istoriją. Kai laikas eina, ir vienas iš mūsų klientų laužiami nes mes pamiršau pabėgti HTML specialius simbolius! Siaubas! Turime išspręsti šią problemą ASAP neprarandant jokių duomenų. Mes nuspręsite naudoti kartas nustebinti mūsų bendraamžiai.
Leiskite atnaujinti schemos vadybininkas (lašas senąjį ir įdiegti naują užsakymą vieną):
& Nbsp; >>> iš zope.component importo globalregistry
& Nbsp; >>> GSM = globalregistry.getGlobalSiteManager ()
& Nbsp; >>> gsm.unregisterUtility (jeigu = ISchemaManager, vardas = 'some.app)
& Nbsp; Tiesa
& Nbsp; >>> klasės MySchemaManager (objektas):
& Nbsp; ... padargai (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... karta = 2
& Nbsp; ...
& Nbsp; ... Def vystytis (savarankiškai, kontekstas, karta):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... atsakymų = šaknis [atsakymus ']
& Nbsp; ... jei karta == 1:
& Nbsp; ... už klausimą, atsakymas answers.items ():
& Nbsp; ... atsakymai [klausimas] = cgi.escape (atsakymas)
& Nbsp; ... Elif kartos == 2:
& Nbsp; ... už klausimą, atsakymas answers.items ():
& Nbsp; ... del atsakymai [klausimas]
& Nbsp; ... atsakymai [cgi.escape (klausimas)] = atsakymas
& Nbsp; ... kitur:
& Nbsp; ... pakelti ValueError ("Nusivylimas")
& Nbsp; ... šaknų [atsakymus '] = atsakymus # ping atkaklumo
& Nbsp; ... transaction.commit ()
& Nbsp; >>> vadybininkas = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (vadovas, ISchemaManager, vardas = 'some.app)
Mes sukūrėme minimum_generation iki 1. Tai reiškia, kad mūsų prašymas bus atsisakyti paleisti su duomenų baze senesnės nei karta 1. kartos požymis yra 2, tai reiškia, kad naujausios kartos, kad tai SchemaManager žino apie tai, 2.
vystytis () yra darbinis arklys čia. Jo darbas yra gauti į duomenų bazę iš kartos-1 į kartą. Ji gauna kontekstą, kuris turi atributą "ryšį", kuris yra prie ZODB ryšys. Galima naudoti, kad pakeisti objektus, kaip šiame pavyzdyje.
Šiuo konkrečiu įgyvendinimo kartos 1 išsiskirs atsakymus (tarkim, kritiškas, nes jie gali būti įrašytas bet kas!), Karta 2 išbėga į klausimus (tarkim, mažiau svarbus, nes jie gali būti įrašyti leidimą Personalo tik).
Tiesą sakant, jums tikrai nereikia pasirinktinį įgyvendinimą ISchemaManager. Vienas iš jų yra prieinama, mes jį naudojo manekeno anksčiau. Jis naudoja Python modulių organizavimo Evolver funkcijas. Žiūrėti savo docstring daugiau informacijos.
Realiame gyvenime turėsite daug daugiau sudėtingų objektų struktūras nei vieno čia. Norėdami, kad jūsų gyvenimas būtų lengvesnis, yra du labai naudingos funkcijos prieinamos zope.generations.utility: findObjectsMatching () ir findObjectsProviding (). Jie bus kasti per konteinerius rekursyviai padėti Jums ieškoti senų daiktų, kuriuos norite atnaujinti per sąsają arba kai kurių kitų kriterijų. Jie yra lengva suprasti, patikrinkite savo docstrings.
kartoms veiksmų
Taigi, mūsų įsiutę klientas parsisiųsti mūsų naujausią kodą ir paleidžiamas Zope. Renginys automatiškai siunčiami vėl:
& Nbsp; >>> įvykis = DatabaseOpenedEventStub (dB)
& Nbsp; >>> evolveMinimumSubscriber (įvykis)
Shazam! Klientas yra laimingas vėl!
& Nbsp; >>> pprint (root [atsakymus '])
& Nbsp; {"Labas": "Sveiki ir kaip jūs darote?",
& Nbsp; "gyvenimo prasmė?": "42",
& Nbsp; "keturių ": "Keturių
& Nbsp; >>> šaknis [generations_key] ['some.app']
& Nbsp; 1
Mes matome, kad kartos dirba, todėl nusprendžia žengti kitą žingsnį ir vystytis kartos 2. Pažiūrėkime, kaip tai galima padaryti rankiniu būdu:
& Nbsp; >>> iš zope.generations.generations importuoti vystytis
& Nbsp; >>> vystytis (dB)
& Nbsp; >>> pprint (root [atsakymus '])
& Nbsp; {"Labas": "Sveiki ir kaip jūs darote?",
& Nbsp; "gyvenimo prasmė?": "42",
& Nbsp; "keturių ": "Keturių
& Nbsp; 2
Įprasta elgsena vystosi atnaujinimų naujausios kartos teikiamos SchemaManager. Jūs galite naudoti, kaip argumentą vystytis (), kai norite tik patikrinti, jei jums reikia atnaujinti ar, jei norite būti tingus, kaip abonentas, kuriuos mes anksčiau vadinamas.
užsakymas schemų vadovų
Dažnai posistemių naudojamas rašyti prašymą remtis kitų posistemių tinkamai veikti. Jei abu posistemės suteikia schemos "vadovams, dažnai naudinga žinoti, kokia tvarka evolvers bus įvykdoma. Tai leidžia sistemą ir tai klientai galės vystytis koncerto, o klientai gali žinoti, kad sistema bus išsivystė prieš arba po save.
Tai gali būti pasiekiama kontroliuojančia schemos vadybininkas komunalinių pavadinimus. Schemos vadovai paleisti nustatyta tvarka rūšiavimo jų vardus.
& Nbsp; >>> manager1 = SchemaManager (minimum_generation = 0, karta = 0)
& Nbsp; >>> manager2 = SchemaManager (minimum_generation = 0, karta = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager1, ISchemaManager, vardas = 'another.app)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager2, ISchemaManager, vardas = 'another.app-plėtinys)
Atkreipkite dėmesį, kaip iš pirmo paketo pavadinimas yra naudojamas sukurti išlaikytinių paketų vardų. Tai nėra iš sistemos reikalavimas, bet patogu modelio šiam naudojimo.
Leiskite vystytis duomenų bazę nustatyti šiuos kartas:
& Nbsp; >>> įvykis = DatabaseOpenedEventStub (dB)
& Nbsp; >>> evolveMinimumSubscriber (įvykis)
& Nbsp; >>> šaknis [generations_key] ['another.app']
& Nbsp; 0
& Nbsp; >>> šaknis [generations_key] ['another.app-plėtinys "]
& Nbsp; 0
Tarkime, kad dėl kokios nors priežasties Kiekvienam iš šių posistemių turi pridėti kartos, ir ta karta 1 "another.app-pratęsimo" priklauso nuo kartos 1 "another.app". Mes turime teikti schemos "vadovams už kiekvieną to įrašo, kad jie buvo paleisti, kad galėtume patikrinti rezultatą:
& Nbsp; >>> gsm.unregisterUtility (jeigu = ISchemaManager, vardas = 'another.app)
& Nbsp; Tiesa
& Nbsp; >>> gsm.unregisterUtility (
& Nbsp; ... jeigu = ISchemaManager, vardas = 'another.app-plėtinys)
& Nbsp; Tiesa
& Nbsp; >>> klasės FoundationSchemaManager (objektas):
& Nbsp; ... padargai (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... karta = 1
& Nbsp; ...
& Nbsp; ... Def vystytis (savarankiškai, kontekstas, karta):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... nutartys = root.get ("užsakymas", [])
& Nbsp; ... jei karta == 1:
& Nbsp; ... ordering.append (pamatų 1)
& Nbsp; ... spausdinimo "pamatai kartos 1"
& Nbsp; ... kitur:
& Nbsp; ... pakelti ValueError ("Nusivylimas")
& Nbsp; ... šaknis ['užsakymo'] = užsakymas # stalo atkaklumas
& Nbsp; ... transaction.commit ()
& Nbsp; >>> klasės DependentSchemaManager (objektas):
& Nbsp; ... padargai (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... karta = 1
& Nbsp; ...
& Nbsp; ... Def vystytis (savarankiškai, kontekstas, karta):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... nutartys = root.get ("užsakymas", [])
& Nbsp; ... jei karta == 1:
& Nbsp; ... ordering.append (priklauso 1)
& Nbsp; ... spausdinimo "priklauso kartos 1"
& Nbsp; ... kitur:
& Nbsp; ... pakelti ValueError ("Nusivylimas")
& Nbsp; ... šaknis ['užsakymo'] = užsakymas # stalo atkaklumas
& Nbsp; ... transaction.commit ()
& Nbsp; >>> manager1 = FoundationSchemaManager ()
& Nbsp; >>> manager2 = DependentSchemaManager ()
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager1, ISchemaManager, vardas = 'another.app)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager2, ISchemaManager, vardas = 'another.app-plėtinys)
Besikeičiantis duomenų bazę dabar visada bus paleisti "another.app" Evolver prieš "another.app-pratęsimo" Evolver:
& Nbsp; >>> įvykis = DatabaseOpenedEventStub (dB)
& Nbsp; >>> evolveMinimumSubscriber (įvykis)
& Nbsp; pamatai karta 1
& Nbsp; priklauso kartos 1
& Nbsp; >>> šaknis ['užsakymo']
& Nbsp; ['pamatai 1 "," priklauso 1']
Diegimas
Į pavyzdyje aukščiau, mes rankiniu būdu inicijuotos, atsakymus. Mes neturėtume to daryti rankiniu būdu. Taikymas turėtų būti suteikta galimybė tai padaryti automatiškai.
IInstallableSchemaManager tęsiasi ISchemaManager, teikiant įdiegti metodą atlikdamas pirminius diegimą paraišką. Tai geresnė alternatyva nei registravimasis bazės atidaryta abonentų.
Leiskite nustatyti naują schemos vadybininką, kuris apima diegimą:
& Nbsp; >>> gsm.unregisterUtility (jeigu = ISchemaManager, vardas = 'some.app)
& Nbsp; Tiesa
& Nbsp; >>> iš zope.generations.interfaces importuoti IInstallableSchemaManager
& Nbsp; >>> klasės MySchemaManager (objektas):
& Nbsp; ... padargai (IInstallableSchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... karta = 2
& Nbsp; ...
& Nbsp; ... Def įdiegti (savarankiškai, kontekstas):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... šaknis [atsakymus '] = {"Labas": "?" Hi & kaip jums tai padaryti ",
& Nbsp; <...> "? Prasmė gyvenimo": "42",
& Nbsp; <...> "keturių ": "Keturių
& Nbsp; ...
& Nbsp; ... Def vystytis (savarankiškai, kontekstas, karta):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... atsakymų = šaknis [atsakymus ']
& Nbsp; ... jei karta == 1:
& Nbsp; ... už klausimą, atsakymas answers.items ():
& Nbsp; ... atsakymai [klausimas] = cgi.escape (atsakymas)
& Nbsp; ... Elif kartos == 2:
& Nbsp; ... už klausimą, atsakymas answers.items ():
& Nbsp; ... del atsakymai [klausimas]
& Nbsp; ... atsakymai [cgi.escape (klausimas)] = atsakymas
& Nbsp; ... kitur:
& Nbsp; ... pakelti ValueError ("Nusivylimas")
& Nbsp; ... šaknų [atsakymus '] = atsakymus # ping atkaklumo
& Nbsp; ... transaction.commit ()
& Nbsp; >>> vadybininkas = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (vadovas, ISchemaManager, vardas = 'some.app)
Dabar, leidžia atidaryti naują duomenų bazėje:
& Nbsp; >>> db.close ()
& Nbsp; >>> db = BP ()
& Nbsp; >>> Conn = db.open ()
& Nbsp; >>> "atsakymų" į conn.root ()
& Nbsp; Neteisingų
& Nbsp; >>> įvykis = DatabaseOpenedEventStub (dB)
& Nbsp; >>> evolveMinimumSubscriber (įvykis)
& Nbsp; >>> conn.sync ()
& Nbsp; >>> root = conn.root ()
& Nbsp; >>> pprint (root [atsakymus '])
& Nbsp; {"Labas": "Sveiki ir kaip jūs darote?",
& Nbsp; "gyvenimo prasmė?": "42",
& Nbsp; "keturių ": "Keturių
& Nbsp; 2
ZODB sandorių žurnale pažymi, kad mūsų įdiegti scenarijų buvo įvykdytas
& Nbsp; >>> [. It.description už jį conn.db () storage.iterator ()] [- 2]
& Nbsp; u'some.app: veikia įdiegti kartos "
(Maža pastaba: tai ne paskutinis įrašas, nes yra du commits: MySchemaManager atlieka vieną ir evolveMinimumSubscriber atlieka antrą kartą MySchemaManager nėra tikrai reikia padaryti.).
Kas naujo , šioje laidoje:.
- Pridėta parama Python 3.3
- Pakeistas pasmerkta zope.interface.implements naudojimas lygiavertis zope.interface.implementer apdailininko.
- Sumažėjo paramą Python 2.4 ir 2.5.
Kas naujo versijos 3.7.1:
- Katilinės statyba Pašalinta dalis, kuri buvo naudojama vystymosi metu, bet daro ne kaupti Windows.
- kartos scenarijus pridėti sandorio dėmesį.
Reikalavimai :
- Python
Komentarai nerastas