Question

I have a library (django-piston) which is expecting some parameters of the class as class properties. I would like to define this value dynamically in a method. So I wanted to do something like:

class MyHandler(BaseHandler):
    @property
    def fields(self):
        fields = self.model._meta.fields + self.model._meta.virtual_fields
        # Do something more with fields
        return fields

But it fails with:

'property' object is not iterable

So I wanted to do something like:

class iterable_property(property):
    def __iter__(self):
        # What here?

But I got stuck here. How could I get a property which can also be iterated over?

Was it helpful?

Solution

Your original code looks fine (though I wouldn't have named the local variable the same name as the enclosing function).

Note, properties only work in new-style classes, so you will need to inherit from object. Also, you need to call the property attribute from an instance.

If you need a class attribute, then property won't work and you'll need to write your own descriptor for a class-level property:

class ClassProperty(object):
    def __init__(self, func):
        self.func = func
    def __get__(self, inst, cls):
        return self.func(cls)

class A(object):
    model_fields = ['field1', 'field2', 'field3']

    @ClassProperty
    def fields(cls):
        return cls.model_fields + ['extra_field']

print A.fields

OTHER TIPS

Sven Marnach pointed me into the right direction. It was not the problem of missing support for iteration in property class, but that it was called on a class. So I made:

class class_property(property):
    def __get__(self, instance, type):
        if instance is None:
            return super(class_property, self).__get__(type, type)
        return super(class_property, self).__get__(instance, type)

and it works now. ;-)

If I've understood things correctly, in django-piston a handler can have a model and fields as class attributes.

If so, your problem could be solved something like this:

class MyHandler(BaseHandler):
    model = Post
    class __metaclass__(type):
        @property
        def fields(cls):
            fields = cls.model._meta.fields + cls.model._meta.virtual_fields
            # Do something more with fields
            return fields
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top