در zope.generations راه به روز رسانی اشیاء در پایگاه داده فراهم می کند زمانی که تغییرات برنامه طرح و nbsp؛ طرح برنامه اساسا ساختار داده ها، ساختار کلاس در مورد ZODB یا توصیف جدول در مورد یک پایگاه داده رابطه ای.
مستندات دقیق
نسل یک راه به روز رسانی اشیاء در پایگاه داده زمانی که تغییرات برنامه طرح. طرح برنامه اساسا ساختار داده ها، ساختار کلاس در مورد ZODB یا توصیف جدول در مورد یک پایگاه داده رابطه ای.
هنگامی که ساختمان داده در برنامه های شما را تغییر دهید، به عنوان مثال، شما به معنای معنایی از یک میدان موجود در یک کلاس را تغییر دهید، شما یک مشکل با پایگاه های داده که قبل از تغییر خود را ایجاد شده اند. برای بحث دقیق تر و راه حل های ممکن، http://wiki.zope.org/zope3/DatabaseGenerations ببینید
ما خواهد شد با استفاده از معماری جزء، و ما یک پایگاه داده و اتصال نیاز:
و nbsp؛ >>> واردات CGI
و nbsp؛ >>> از pprint واردات pprint
و nbsp؛ >>> از zope.interface ادوات واردات
و nbsp؛ >>> از ZODB.tests.util واردات DB
و nbsp؛ >>> DB = DB ()
و nbsp؛ >>> هدایت کردن = db.open ()
و nbsp؛ >>> ریشه = conn.root ()
تصور کنید که برنامه ما اوراکل است: شما می توانید آن را به واکنش نشان می دهند به عبارت آموزش. اجازه دهید آن را ساده نگه دارید و ذخیره داده ها در یک DICT:
و nbsp؛ >>> ریشه ['پاسخ'] = {'سلام': 'سلام و چگونه کار می کنی،
و nbsp؛ ... '؟ معنای زندگی': '42'،
و nbsp؛ ... 'چهار <؟': 'چهار <پنج'}
و nbsp؛ >>> معامله واردات
و nbsp؛ >>> transaction.commit ()
راه اندازی اولیه
در اینجا برخی از کد نسل خاص است. ما ایجاد خواهد شد و ثبت نام SchemaManager. SchemaManagers مسئول به روز رسانی واقعی از پایگاه داده می باشد. این یکی خواهد بود فقط نوک پستان. نکته در اینجا این است که نسل ماژول آگاه باشید که برنامه ما پشتیبانی نسل.
اجرای به طور پیش فرض از SchemaManager است مناسب برای این آزمون نه به خاطر آن استفاده می کند ماژول پایتون برای مدیریت نسل. در حال حاضر، از آن خواهد شد فقط خوب است، از آنجایی که ما نمی خواهیم آن را به انجام هر کاری درست نشده است.
و nbsp؛ >>> از zope.generations.interfaces وارد ISchemaManager
و nbsp؛ >>> از zope.generations.generations وارد SchemaManager
و nbsp؛ >>> واردات zope.component
و nbsp؛ >>> dummy_manager = SchemaManager (minimum_generation = 0، نسل = 0)
و nbsp؛ >>> zope.component.provideUtility (
و nbsp؛ ... dummy_manager، ISchemaManager، نام = 'some.app')
'some.app' یک شناسه منحصر به فرد است. شما باید یک URI یا نام نقطه چین از بسته بندی خود را استفاده کنید.
هنگامی که شما شروع Zope و یک پایگاه داده باز است، IDatabaseOpenedWithRoot رویداد فرستاده شده است. Zope ثبت evolveMinimumSubscriber به طور پیش فرض به عنوان یک کنترل برای این رویداد. بیایید این شبیه سازی:
و nbsp؛ >>> DatabaseOpenedEventStub کلاس (شی):
و nbsp؛ ... دف __init __ (خود، پایگاه داده):
و nbsp؛ ... self.database = پایگاه داده
و nbsp؛ >>> رویداد = DatabaseOpenedEventStub (DB)
و nbsp؛ >>> از zope.generations.generations وارد evolveMinimumSubscriber
و nbsp؛ >>> evolveMinimumSubscriber (رویداد)
نتیجه این عمل این است که در حال حاضر پایگاه داده شامل این واقعیت است که تعداد طرح فعلی ما 0. وقتی است که ما طرح به روز رسانی، Zope3 خواهد یک ایده از آنچه نقطه شروع بود داشته باشد. در اینجا، ببینید؟
و nbsp؛ >>> از zope.generations.generations وارد generations_key
و nbsp؛ >>> ریشه [generations_key] ['some.app']
& nbsp؛ در 0
در زندگی واقعی هرگز به شما باید به زحمت با این کلید به طور مستقیم، اما شما باید آگاه باشید که آن وجود دارد.
سناریو ارتقا
بازگشت به داستان. برخی از زمان عبور می کند و یکی از مشتریان ما هک می شود چرا که ما را فراموش کرده به فرار از کاراکترهای خاص HTML! وحشت! ما باید این مشکل ASAP بدون از دست دادن هر گونه اطلاعات را حل کنند. ما تصمیم به استفاده از نسل به تحت تاثیر قرار دادن همسالان ما.
بیایید به روز رسانی مدیر طرح (رها یکی از قدیمی و نصب سفارشی جدید):
و nbsp؛ >>> از zope.component globalregistry واردات
و nbsp؛ >>> GSM = globalregistry.getGlobalSiteManager ()
و nbsp؛ >>> gsm.unregisterUtility (ارائه = ISchemaManager، نام = 'some.app')
و nbsp؛ واقعی
و nbsp؛ >>> MySchemaManager کلاس (شی):
و nbsp؛ ... ادوات (ISchemaManager)
& nbsp؛ در ...
و nbsp؛ ... minimum_generation = 1
را لمس کنید و. ... نسل = 2
& nbsp؛ در ...
و nbsp؛ ... دف تکامل (خود، زمینه، نسل):
و nbsp؛ ... ریشه = context.connection.root ()
و nbsp؛ ... پاسخ = ریشه ['پاسخ']
و nbsp؛ ... اگر نسل == 1:
و nbsp؛ ... برای سوال، پاسخ در answers.items ():
و nbsp؛ ... پاسخ [سوال] = cgi.escape (پاسخ)
و nbsp؛ ... نسل الیف == 2:
و nbsp؛ ... برای سوال، پاسخ در answers.items ():
و nbsp؛ ... دل پاسخ [سوال]
را لمس کنید و. ... پاسخ [cgi.escape (سوال)] = پاسخ
و nbsp؛ ... دیگری:
و nbsp؛ ... افزایش ValueError ("بد شانسی")
و nbsp؛ ... ریشه ['پاسخ'] = پاسخ تداوم # پینگ
و nbsp؛ ... transaction.commit ()
و nbsp؛ >>> مدیر = MySchemaManager ()
و nbsp؛ >>> zope.component.provideUtility (مدیر، ISchemaManager، نام = 'some.app')
ما minimum_generation به 1. تعیین کرده اند که بدان معنی است که برنامه خود را به اجرا با یک پایگاه داده مسن تر از نسل 1. ویژگی نسل به 2 مجموعه، که بدان معنی است که جدیدترین نسل که این SchemaManager می داند در مورد 2 است رد خواهد شد.
تکامل () اسب بارکش اینجا است. کار آن است که برای دریافت پایگاه داده از نسل-1 به نسل. این می شود یک زمینه است که ویژگی "اتصال" است، که یک اتصال به ZODB. شما می توانید برای تغییر اشیاء مانند در این مثال استفاده از آن.
در این نسل اجرای خاص 1 فرار پاسخ (مثلا، مهم، چرا که آنها را می توان با هر کسی وارد!)، نسل 2 سوالات فرار (مثلا، کم اهمیت تر، چرا که این را می توان با مجاز personell تنها وارد).
در واقع، شما واقعا نیاز اجرای سفارشی از ISchemaManager. یکی در دسترس است، ما آن را برای یک ساختگی قبلا استفاده می شود. آن استفاده می کند ماژول پایتون برای سازمان از توابع evolver. رشته مستندساز خود را برای اطلاعات بیشتر ببینید.
در زندگی واقعی شما ساختار بسیار بیشتر شی پیچیده تر از اینجا. برای اینکه زندگی شما را آسانتر، دو توابع بسیار مفید موجود در zope.generations.utility وجود دارد: findObjectsMatching () و findObjectsProviding (). آنها را از طریق ظروف به صورت بازگشتی حفاری به شما کمک کند به دنبال اشیاء قدیمی که می خواهید برای به روز رسانی، توسط رابط و یا توسط برخی از معیارهای دیگر. آنها به آسانی قابل درک، بررسی docstrings خود هستند.
نسل در عمل
بنابراین، مشتری خشمگین ما دریافت آخرین کد ما و شروع مجدد Zope. این رویداد به طور خودکار دوباره فرستاده:
و nbsp؛ >>> رویداد = DatabaseOpenedEventStub (DB)
و nbsp؛ >>> evolveMinimumSubscriber (رویداد)
Shazam را! مشتری خوشحال است دوباره!
و nbsp؛ >>> pprint (ریشه ['پاسخ'])
و nbsp؛ {'سلام': 'سلام و چگونه کار می کنی؟ "،
& nbsp؛ در 'معنای زندگی؟': '42'،
& nbsp؛ در 'چهار <؟': 'چهار <پنج'}
از آنجا که evolveMinimumSubscriber بسیار تنبل است، آن را تنها به روز رسانی پایگاه داده فقط به اندازه کافی به طوری که نرم افزار شما می تواند از آن استفاده کنید (به minimum_generation، که است). در واقع، نشانگر نشان می دهد که نسل پایگاه داده است تا 1، ضربه:
و nbsp؛ >>> ریشه [generations_key] ['some.app']
و nbsp؛ 1
ما می بینیم که نسل در حال کار است، بنابراین ما تصمیم به گرفتن گام بعدی و تکامل به نسل 2. بیایید ببینید که چگونه این می تواند به صورت دستی انجام می شود:
و nbsp؛ >>> از zope.generations.generations وارد تکامل
و nbsp؛ >>> تکامل (DB)
و nbsp؛ >>> pprint (ریشه ['پاسخ'])
و nbsp؛ {'سلام': 'سلام و چگونه کار می کنی؟ "،
& nbsp؛ در 'معنای زندگی؟': '42'،
& nbsp؛ در 'چهار <؟': 'چهار <پنج'}
و nbsp؛ >>> ریشه [generations_key] ['some.app']
و nbsp؛ 2
به طور پیش فرض رفتار ارتقاء تکامل به آخرین نسل ارائه شده توسط SchemaManager. شما می توانید استدلال که چگونه به تکامل زمانی که می خواهید فقط برای بررسی اگر شما نیاز به به روز رسانی و یا اگر شما می خواهید به تنبل مثل مشترک که ما قبلا به نام استفاده از ().
دعوت از مدیران طرح
غالبا زیر سیستم در زیر سیستم های دیگر استفاده می شود به سرودن یک برنامه تکیه به کار به درستی. اگر هر دو زیر سیستم ارائه مدیران طرح، آن است که اغلب مفید می دانید منظور که در آن evolvers استناد خواهد شد. این اجازه می دهد تا یک چارچوب و آن را به مشتریان قادر به تکامل در کنسرت، و مشتریان می تواند می دانیم که چارچوب خواهد شد قبل یا بعد از خود تبدیل شده است.
این را می توان با کنترل نام آب و برق مدیر طرح انجام می شود. مدیران طرح ها در جهت تعیین شده توسط مرتب سازی نام خود را اجرا کنید.
و nbsp؛ >>> manager1 = SchemaManager (minimum_generation = 0، نسل = 0)
و nbsp؛ >>> manager2 = SchemaManager (minimum_generation = 0، نسل = 0)
و nbsp؛ >>> zope.component.provideUtility (
و nbsp؛ ... manager1، ISchemaManager، نام = 'another.app')
و nbsp؛ >>> zope.component.provideUtility (
و nbsp؛ ... manager2، ISchemaManager، نام = 'another.app-پسوند)
توجه کنید که چگونه به نام بسته برای اولین بار استفاده می شود برای ایجاد یک فضای نامی برای بسته وابسته است. این یک نیاز از چارچوب، اما یک الگوی مناسب برای این استفاده نمی شود.
بیایید تکامل پایگاه داده برای ایجاد این نسل:
و nbsp؛ >>> رویداد = DatabaseOpenedEventStub (DB)
و nbsp؛ >>> evolveMinimumSubscriber (رویداد)
و nbsp؛ >>> ریشه [generations_key] ['another.app']
& nbsp؛ در 0
و nbsp؛ >>> ریشه [generations_key] ['another.app-پسوند]
& nbsp؛ در 0
بیایید فرض کنیم که برای برخی از دلیل هر یک از این زیر سیستم نیاز به اضافه کردن یک نسل، و نسل 1 از 'another.app-پسوند بستگی به نسل 1 از' another.app. ما باید به ارائه مدیران طرح برای هر که رکورد که آنها را اجرا کرده ام بنابراین ما می توانیم نتیجه بررسی:
و nbsp؛ >>> gsm.unregisterUtility (ارائه = ISchemaManager، نام = 'another.app')
و nbsp؛ واقعی
و nbsp؛ >>> gsm.unregisterUtility (
و nbsp؛ ... ارائه = ISchemaManager، نام = 'another.app-پسوند)
و nbsp؛ واقعی
و nbsp؛ >>> کلاس FoundationSchemaManager (شی):
و nbsp؛ ... ادوات (ISchemaManager)
& nbsp؛ در ...
و nbsp؛ ... minimum_generation = 1
را لمس کنید و. ... نسل = 1
& nbsp؛ در ...
و nbsp؛ ... دف تکامل (خود، زمینه، نسل):
و nbsp؛ ... ریشه = context.connection.root ()
& nbsp؛ در ... سفارش = root.get ('سفارش، [])
و nbsp؛ ... اگر نسل == 1:
و nbsp؛ ... ordering.append ('بنیاد 1)
و nbsp؛ ... 'نسل بنیاد 1' چاپ
و nbsp؛ ... دیگری:
و nbsp؛ ... افزایش ValueError ("بد شانسی")
را لمس کنید و ... ریشه ['سفارش'] = سفارش تداوم # پینگ
و nbsp؛ ... transaction.commit ()
و nbsp؛ >>> DependentSchemaManager کلاس (شی):
و nbsp؛ ... ادوات (ISchemaManager)
& nbsp؛ در ...
و nbsp؛ ... minimum_generation = 1
را لمس کنید و. ... نسل = 1
& nbsp؛ در ...
و nbsp؛ ... دف تکامل (خود، زمینه، نسل):
و nbsp؛ ... ریشه = context.connection.root ()
& nbsp؛ در ... سفارش = root.get ('سفارش، [])
و nbsp؛ ... اگر نسل == 1:
و nbsp؛ ... ordering.append ('وابسته به 1')
و nbsp؛ ... نسخه قابل چاپ "نسل وابسته به 1 '
و nbsp؛ ... دیگری:
و nbsp؛ ... افزایش ValueError ("بد شانسی")
را لمس کنید و ... ریشه ['سفارش'] = سفارش تداوم # پینگ
و nbsp؛ ... transaction.commit ()
و nbsp؛ >>> manager1 = FoundationSchemaManager ()
و nbsp؛ >>> manager2 = DependentSchemaManager ()
و nbsp؛ >>> zope.component.provideUtility (
و nbsp؛ ... manager1، ISchemaManager، نام = 'another.app')
و nbsp؛ >>> zope.component.provideUtility (
و nbsp؛ ... manager2، ISchemaManager، نام = 'another.app-پسوند)
در حال تحول پایگاه داده در حال حاضر همیشه 'another.app' evolver قبل از 'another.app-پسوند evolver را اجرا کنید:
و nbsp؛ >>> رویداد = DatabaseOpenedEventStub (DB)
و nbsp؛ >>> evolveMinimumSubscriber (رویداد)
نسل 1 پایه، و nbsp
& nbsp؛ از نسل وابسته 1
و nbsp؛ >>> ریشه ['سفارش']
و nbsp؛ ['بنیاد 1'، 'وابسته به 1']
نصب
در مثال بالا، ما دستی پاسخ اولیه. ما نباید به انجام این کار دستی. برنامه باید قادر به انجام این کار به طور خودکار باشد.
IInstallableSchemaManager گسترش ISchemaManager، ارائه یک روش نصب برای انجام یک نصب و راه اندازی اولیه یک برنامه کاربردی. این یک جایگزین بهتر از ثبت نام مشترکین-پایگاه داده باز است.
اجازه دهید یک مدیر طرح جدید که شامل نصب و راه اندازی تعریف:
و nbsp؛ >>> gsm.unregisterUtility (ارائه = ISchemaManager، نام = 'some.app')
و nbsp؛ واقعی
و nbsp؛ >>> از zope.generations.interfaces وارد IInstallableSchemaManager
و nbsp؛ >>> MySchemaManager کلاس (شی):
و nbsp؛ ... ادوات (IInstallableSchemaManager)
& nbsp؛ در ...
و nbsp؛ ... minimum_generation = 1
را لمس کنید و. ... نسل = 2
& nbsp؛ در ...
و nbsp؛ ... دف نصب (خود، زمینه):
و nbsp؛ ... ریشه = context.connection.root ()
و nbsp؛ ... ریشه ['پاسخ'] = {'سلام': 'سلام و چگونه کار می کنی،
و nbsp؛ ... '؟ معنای زندگی': '42'،
و nbsp؛ ... 'چهار <؟': 'چهار <پنج'}
و nbsp؛ ... transaction.commit ()
& nbsp؛ در ...
و nbsp؛ ... دف تکامل (خود، زمینه، نسل):
و nbsp؛ ... ریشه = context.connection.root ()
و nbsp؛ ... پاسخ = ریشه ['پاسخ']
و nbsp؛ ... اگر نسل == 1:
و nbsp؛ ... برای سوال، پاسخ در answers.items ():
و nbsp؛ ... پاسخ [سوال] = cgi.escape (پاسخ)
و nbsp؛ ... نسل الیف == 2:
و nbsp؛ ... برای سوال، پاسخ در answers.items ():
و nbsp؛ ... دل پاسخ [سوال]
را لمس کنید و. ... پاسخ [cgi.escape (سوال)] = پاسخ
و nbsp؛ ... دیگری:
و nbsp؛ ... افزایش ValueError ("بد شانسی")
و nbsp؛ ... ریشه ['پاسخ'] = پاسخ تداوم # پینگ
و nbsp؛ ... transaction.commit ()
و nbsp؛ >>> مدیر = MySchemaManager ()
و nbsp؛ >>> zope.component.provideUtility (مدیر، ISchemaManager، نام = 'some.app')
در حال حاضر، اجازه می دهد تا باز کردن یک پایگاه داده جدید:
و nbsp؛ >>> db.close ()
و nbsp؛ >>> DB = DB ()
و nbsp؛ >>> هدایت کردن = db.open ()
& nbsp؛ در 'پاسخ' >>> در conn.root ()
و nbsp؛ کاذب
و nbsp؛ >>> رویداد = DatabaseOpenedEventStub (DB)
و nbsp؛ >>> evolveMinimumSubscriber (رویداد)
و nbsp؛ >>> conn.sync ()
و nbsp؛ >>> ریشه = conn.root ()
و nbsp؛ >>> pprint (ریشه ['پاسخ'])
و nbsp؛ {'سلام': 'سلام و چگونه کار می کنی؟ "،
& nbsp؛ در 'معنای زندگی؟': '42'،
& nbsp؛ در 'چهار <؟': 'چهار <پنج'}
و nbsp؛ >>> ریشه [generations_key] ['some.app']
و nbsp؛ 2
ورود معامله ZODB اشاره می کند که اسکریپت نصب ما اعدام شد
و nbsp؛ >>> [. it.description برای آن در conn.db () storage.iterator ()] [- 2]
& nbsp؛ در u'some.app: در حال اجرا نصب نسل '
(توجه داشته باشید صغیر: این طور نیست آخرین رکورد به دلیل دو تصدیق وجود دارد:.. MySchemaManager یک انجام، و evolveMinimumSubscriber دوم انجام MySchemaManager واقعا نمی باید متعهد)
چه جدید در این نسخه است:
اضافه شدن پشتیبانی از پایتون 3.3.
جایگزین استفاده zope.interface.implements توصیه با دکوراتور zope.interface.implementer معادل.
پشتیبانی از پایتون 2.4 و 2.5 کاهش یافته است.
جدید در نسخه 3.7.1 است:
به حذف بخشی buildout که در طول توسعه مورد استفاده قرار گرفت اما در ویندوز کامپایل نیست.
اسکریپت ایجاد اضافه کردن یک یادداشت معامله.
مورد نیاز:
پایتون
نظر یافت نشد