zope.generations

البرمجيات قطة:
zope.generations
تفاصيل البرنامج:
الإصدار: 4.0.0 Alpha 1
تاريخ إيداع: 15 Apr 15
ترخيص: حرر
شعبية: 2

Rating: nan/5 (Total Votes: 0)

و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 ()
على & nbsp؛ >>> كون = db.open ()
على & nbsp؛ >>> الجذر = conn.root ()
تخيل أن طلبنا هو أوراكل: يمكنك تدريسه للرد على العبارات. دعونا يبقيه بسيط وتخزين البيانات في ديكت:
على & nbsp؛ >>> الجذر ['إجابات'] = {'مرحبا': '؟ مرحبا وكيف يمكنك أن تفعل،
على & nbsp؛ ... '؟ معنى الحياة': '42'،
على & 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 (ديسيبل)
على & nbsp؛ >>> من zope.generations.generations استيراد evolveMinimumSubscriber
على & nbsp؛ >>> evolveMinimumSubscriber (الحدث)
ونتيجة لهذا العمل هو أن الآن تحتوي قاعدة البيانات على حقيقة أن لدينا عدد المخطط الحالي هو 0. عندما وتحديث المخطط، سوف Zope3 لديك فكرة عن ما كانت نقطة البداية. هنا، ترى؟
على & nbsp؛ >>> من zope.generations.generations استيراد generations_key
على & nbsp؛ >>> الجذر [generations_key] ['some.app']
على & nbsp؛ 0
في الحياة الحقيقية يجب أن يكون أبدا لعناء مع هذا المفتاح مباشرة، ولكن يجب أن تكون على علم أنه موجود.
السيناريو الترقية
العودة إلى القصة. بعض الوقت يمر واحد من عملائنا يحصل اختراق لأننا نسيت أن الهروب أحرف خاصة HTML! الرعب! يجب علينا إصلاح هذه المشكلة في اسرع وقت ممكن دون فقدان أية بيانات. قررنا استخدام أجيال لإقناع أقراننا.
دعونا تحديث مدير المخطط (قطرة واحدة من العمر وتثبيت مخصص جديد واحد):
على & nbsp؛ >>> من zope.component globalregistry استيراد
على & nbsp؛ >>> جي إس إم = globalregistry.getGlobalSiteManager ()
على & nbsp؛ >>> gsm.unregisterUtility (شريطة = ISchemaManager، اسم = 'some.app')
على & nbsp؛ صحيح
على & nbsp؛ >>> MySchemaManager فئة (كائن):
على & nbsp؛ ... الأدوات (ISchemaManager)
على & nbsp؛ ...
على & nbsp؛ ... minimum_generation = 1
على & nbsp؛ ... الجيل = 2
على & nbsp؛ ...
على & nbsp؛ ... تتطور مواطنه (النفس، والسياق، وتوليد):
على & nbsp؛ ... الجذر = context.connection.root ()
على & nbsp؛ ... أجوبة = الجذر ['إجابات']
على & nbsp؛ ... إذا الجيل == 1:
على & nbsp؛ ... السؤال، والإجابة في answers.items ():
على & nbsp؛ ... الأجوبة [السؤال] = cgi.escape (الجواب)
على & nbsp؛ ... الجيل أليف == 2:
على & nbsp؛ ... السؤال، والإجابة في answers.items ():
على & nbsp؛ ... ديل الأجوبة [السؤال]
على & 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 يهرب من الأسئلة (مثلا، أقل أهمية، لأن هذه يمكن إدخالها من قبل المأذون بيرسونيل فقط).
في الواقع، كنت لا حقا في حاجة الى تنفيذ مخصص من ISchemaManager. كان متوفرا، وقد استخدمنا ذلك لدمية سابقا. ويستخدم وحدات بيثون في تنظيم وظائف evolver. انظر docstring من أجل مزيد من المعلومات.
في الحياة الحقيقية سيكون لديك هياكل وجوه أكثر من ذلك بكثير تعقيدا من احد هنا. لتجعل حياتك أسهل، وهناك نوعان من الوظائف المفيدة للغاية المتاحة في zope.generations.utility: findObjectsMatching () وfindObjectsProviding (). وسوف حفر من خلال حاويات بشكل متكرر لمساعدتك بحث عن الأشياء القديمة التي كنت ترغب في تحديث، من خلال واجهة أو عن طريق بعض المعايير الأخرى. فهي سهلة لفهم، والتحقق من جمل التوثيق الخاصة بهم.
أجيال في العمل
لذا، عميل غاضب لدينا بتحميل أحدث نظامنا وإعادة تشغيل Zope. يتم إرسال الحدث تلقائيا مرة أخرى:
على & nbsp؛ >>> الحدث = DatabaseOpenedEventStub (ديسيبل)
على & nbsp؛ >>> evolveMinimumSubscriber (الحدث)
الصويغ! العميل هو سعيد مرة أخرى!
على & nbsp؛ >>> pprint (الجذر ['إجابات'])
على & nbsp؛ {'مرحبا': 'مرحبا وكيف يمكنك أن تفعل؟ "،
على & nbsp؛ "معنى الحياة؟ ':' 42 '،
على & nbsp؛ "أربعة <؟ ':' أربعة <الخمسة}
لأن evolveMinimumSubscriber هو كسول جدا، فإنه يقوم بتحديث قاعدة البيانات فقط ما يكفي لذلك أن التطبيق الخاص بك لا يمكن استخدامها (لminimum_generation، وهذا هو). في الواقع، تشير علامة أن الجيل قاعدة بيانات تم صدم ل1:
على & nbsp؛ >>> الجذر [generations_key] ['some.app']
على & nbsp؛ 1
ونحن نرى أن الأجيال تعمل، لذلك قررنا اتخاذ الخطوة التالية وتتطور إلى جيل 2. دعونا نرى كيف يمكن القيام بذلك يدويا:
على & nbsp؛ >>> من zope.generations.generations استيراد تتطور
على & nbsp؛ >>> تتطور (ديسيبل)
على & 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 (ديسيبل)
على & 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
على & nbsp؛ ... الجيل = 1
على & nbsp؛ ...
على & nbsp؛ ... تتطور مواطنه (النفس، والسياق، وتوليد):
على & nbsp؛ ... الجذر = context.connection.root ()
على & nbsp؛ ... ترتيب = root.get ('ترتيب'، [])
على & nbsp؛ ... إذا الجيل == 1:
على & nbsp؛ ... ordering.append ('الأساس 1')
على & nbsp؛ ... طباعة 'جمعية جيل 1 "
على & nbsp؛ ... آخر:
على & nbsp؛ ... رفع ValueError ("المشكله")
على & nbsp؛ ... الجذر ['ترتيب'] = ترتيب # بينغ استمرار
على & nbsp؛ ... transaction.commit ()
على & nbsp؛ >>> DependentSchemaManager فئة (كائن):
على & nbsp؛ ... الأدوات (ISchemaManager)
على & nbsp؛ ...
على & nbsp؛ ... minimum_generation = 1
على & nbsp؛ ... الجيل = 1
على & nbsp؛ ...
على & nbsp؛ ... تتطور مواطنه (النفس، والسياق، وتوليد):
على & nbsp؛ ... الجذر = context.connection.root ()
على & nbsp؛ ... ترتيب = root.get ('ترتيب'، [])
على & nbsp؛ ... إذا الجيل == 1:
على & nbsp؛ ... ordering.append ('تعتمد 1')
على & nbsp؛ ... طباعة 'جيل يعتمد 1 "
على & nbsp؛ ... آخر:
على & nbsp؛ ... رفع ValueError ("المشكله")
على & nbsp؛ ... الجذر ['ترتيب'] = ترتيب # بينغ استمرار
على & 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 (ديسيبل)
على & nbsp؛ >>> evolveMinimumSubscriber (الحدث)
على & nbsp؛ جيل الأساس 1
على & nbsp؛ جيل يعتمد 1
على & nbsp؛ >>> الجذر ['ترتيب']
على & nbsp؛ ['الأساس 1'، 'تعتمد 1']
تركيب
في المثال أعلاه، فإننا تهيئة الإجابات يدويا. لا ينبغي لنا أن يجب أن نفعل ذلك يدويا. وينبغي أن تكون قادرة على القيام بذلك تلقائيا التطبيق.
IInstallableSchemaManager يمتد ISchemaManager، وتوفير تثبيت طريقة لإجراء تثبيت intial من تطبيق. هذا هو بديل أفضل من تسجيل المشتركين فتح قاعدة البيانات.
دعونا تعريف مدير المخطط الجديد الذي يشمل تركيب:
على & nbsp؛ >>> gsm.unregisterUtility (شريطة = ISchemaManager، اسم = 'some.app')
على & nbsp؛ صحيح
على & nbsp؛ >>> من zope.generations.interfaces استيراد IInstallableSchemaManager
على & nbsp؛ >>> MySchemaManager فئة (كائن):
على & nbsp؛ ... الأدوات (IInstallableSchemaManager)
على & nbsp؛ ...
على & nbsp؛ ... minimum_generation = 1
على & nbsp؛ ... الجيل = 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؛ ... ديل الأجوبة [السؤال]
على & nbsp؛ ... الأجوبة [cgi.escape (السؤال)] = الجواب
على & nbsp؛ ... آخر:
على & nbsp؛ ... رفع ValueError ("المشكله")
على & nbsp؛ ... الجذر ['إجابات'] = إجابات # بينغ استمرار
على & nbsp؛ ... transaction.commit ()
على & nbsp؛ >>> مدير = MySchemaManager ()
على & nbsp؛ >>> zope.component.provideUtility (إداري، ISchemaManager، اسم = 'some.app')
الآن، يتيح فتح قاعدة بيانات جديدة:
على & nbsp؛ >>> db.close ()
على & nbsp؛ >>> ديسيبل = DB ()
على & nbsp؛ >>> كون = db.open ()
على & nbsp؛ >>> "إجابات" في conn.root ()
على & nbsp؛ خطأ
على & nbsp؛ >>> الحدث = DatabaseOpenedEventStub (ديسيبل)
على & 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 التي تم استخدامها أثناء تطوير ولكن لا يجمع على ويندوز.
مخطوطات الجيل تضيف مذكرة المعاملة.

المتطلبات:

بيثون

البرامج الأخرى من المطور Zope Corporation and Contributors

تعليقات ل zope.generations

لم يتم العثور على التعليقات
إضافة تعليق
بدوره على الصور!