Zope: cannot access REQUEST under property decorator

后端 未结 2 1737
失恋的感觉
失恋的感觉 2021-01-05 14:34

I\'m trying to use the property decorator in a Class. While it works well per se, I can\'t use any code that has to access the REQUEST.

class So         


        
相关标签:
2条回答
  • 2021-01-05 15:04

    The property decorator only works with new-style classes; that is to say, classes that inherit from object. Acquisition (which gives you access to the global REQUEST object via attribute access) on the other hand is very much 'old-skool' python and the two do not work well together, as property ignores acquisition wrappers, which are needed to acquire the REQUEST object.

    Zope has it's own property-like method that pre-dates new-style classes and the property decorater, called ComputedAttribute, which actually predates the property decorator and new-style classes by many years. A ComputedAttribute-wrapped function does know how to behave with an Acquisition-wrapped object, though.

    You can use ComputedAttibute much like the property decorator:

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

    The ComputedAttribute wrapper function also can be configured with a level of wrapping, which is what we need when dealing with Acquisition wrappers. You cannot use the ComputedAttribute as a decorator in that case:

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

    It is easy enough to define a new function to do the decorating for us though:

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

    Stick this in a utility module somewhere, after which you can then use it as a callable decorator to mark something as an Acquisition-aware property:

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

    Note that unlike property, ComputedAttribute can only be used for getters; there is no support for setters or deleters.

    0 讨论(0)
  • 2021-01-05 15:26

    If you want to route around needing acquisition and cannot explicitly set the request from calling code in the constructor of your class, use zope.globalrequest. Otherwise, you may want to consider a browser view (which always multi-adapts some context and a request).

    0 讨论(0)
提交回复
热议问题