2012-09-22 17 views
6

Sto tentando di utilizzare il decoratore di proprietà in una classe. Sebbene funzioni di per sé, non posso usare alcun codice che deve accedere allo REQUEST.Zope: impossibile accedere alla RICHIESTA sotto il decoratore di proprietà

class SomeClass(): 
    #Zope magic code 
    _properties=({'id':'someValue', 'type':'ustring', 'mode':'r'},) 

    def get_someValue(self): 
    return self.REQUEST 

    @property 
    def someValue(self): 
    return self.REQUEST 

Anche se chiamando get_someValue me ottiene il risultato desiderato, si tenta di accedere someValue solleva un AttributeError.

Qual è la logica dietro questo comportamento? C'è un modo per aggirare questa limitazione?

(sto usando Zope 2.13.16, Python 2.7.3)

+0

Si utilizza una classe base come Persistenza o Acquisizione? –

+0

Ho ObjectManager come una delle classi base (che eredita da Persistent) – Rastaf

+0

e Acquisition.Implicit. :-) –

risposta

6

L'property decorator funziona solo con new-style classi; Vale a dire, le classi che ereditano da object. D'altra parte, l'acquisizione (che consente l'accesso all'oggetto globale REQUEST tramite accesso agli attributi) è molto "vecchio-skool" python e le due non funzionano bene insieme, come propertyignora i wrapper di acquisizione, che sono necessari per acquisire l'oggetto REQUEST.

Zope ha il proprio property -come metodo che precede classi di nuovo stile e la property decorater, chiamato ComputedAttribute, che precede in realtà le classi property decoratore e nuovo stile da molti anni. Una funzione wrapping ComputedAttribute non sa come comportarsi con un oggetto con spostamento Acquisition, tuttavia.

È possibile utilizzare ComputedAttibute molto simile al property decoratore:

from ComputedAttribute import ComputedAttribute 

class SomeClass(): 
    @ComputedAttribute 
    def someProperty(self): 
     return 'somevalue' 

La funzione ComputedAttribute involucro può anche essere configurato con un livello di involucro, che è quello che ci serve quando si tratta di involucri di acquisizione. Non è possibile utilizzare il ComputedAttribute come decoratore in quel caso:

class SomeClass(): 
    def someValue(self): 
     return self.REQUEST 
    someValue = ComputedAttribute(someValue, 1) 

E 'abbastanza facile definire una nuova funzione per fare la decorazione per noi però:

from ComputedAttribute import ComputedAttribute 

def computed_attribute_decorator(level=0): 
    def computed_attribute_wrapper(func): 
     return ComputedAttribute(func, level) 
    return computed_attribute_wrapper 

Stick questo in un modulo di utilità da qualche parte , dopo di che è possibile utilizzare come un decoratore callable per segnare qualcosa come una proprietà di acquisizione-aware:

class SomeClass(): 
    @computed_attribute_decorator(level=1) 
    def someValue(self): 
     return self.REQUEST 

si noti che diversamente property, ComputedAttribute può essere utilizzato solo per getter; non c'è supporto per setter o deleter.

+1

Grazie mille! Sto usando Zope già da un paio d'anni e non sono mai incappato nel metodo ComputedAttribute. – Rastaf

+0

Questo sembra funzionare per me in un caso (oggetto di contenuto di Plone/Dexterity), ma a scopo di chiarimento: ci sono effetti collaterali noti nell'usare decoratore basato su ComputedAttribute come questo su classi di nuovo stile? Quali classi base devono estendere una classe per utilizzare ComputedAttribute (ad esempio, in una vista del browser che partecipa all'acquisizione)? – sdupton

+1

È possibile utilizzare ComputedAttribute solo su classi derivate da'ExtensionClass' (che include le classi 'Acquisition.Explicit' e' Acquisition.Implicit'). Oltre a questo non ci sono altri requisiti. –

3

Se si desidera eseguire il routing in base all'acquisizione e non è possibile impostare esplicitamente la richiesta dal codice di chiamata nel costruttore della classe, utilizzare zope.globalrequest. Altrimenti, potresti prendere in considerazione una vista del browser (che adatta sempre un po 'di contesto e una richiesta).

+0

Grazie per avermi indirizzato a zope.globalrequest. Non ho il pacchetto installato, quindi proverò se ho bisogno di aggirare l'acquisizione. Al momento sono perfettamente soddisfatto della risposta fornita da Martijn Pieters. Cosa intendi con "considerando una vista del browser"? – Rastaf