Reputation: 150
I have no idea how to even look for this, here is a simplified example
I have a class:
class MyField():
def __init__(self, model=None, source=None, id=None):
self.source = source
self.model = model
self.id = id
def somemethod(self):
...
That is used on this other class
class MyClass(db.Model):
id = db.Column(db.Integer, primary_key=True)
somefield = db.Column(db.String(255))
@property
def someproperty(self):
specs = MyField(
source=self.somefield,
model=self.__class__.__name__,
id=self.id
)
return specs.somemethod()
By that is no ideal to me, I want to have something simpler to code for the second class, so making it look like this:
class MyClass(db.Model):
somefield = db.Column(db.String(255))
someproperty = MyField(source='somefield')
and have on the first class all the logic that handles that data. Here I have no idea on how to read the contents of 'somefield' and id, 'somefield' may vary and have another name, thats why I use it as an argument, and 'id' is always the same for every class
Upvotes: 0
Views: 91
Reputation: 365717
All that @property
does is return a custom descriptor whose __get__
method calls your function. So, you can just do that directly.
I can't test this, because I don't have sqlalchemy
installed here, but something like this:
class FieldProperty(object):
def __init__(self, field, source):
self.field, self.source = field, source
def __get__(self, obj, typ=None):
if typ is None:
typ = obj.__class__
specs = self.field(
source = getattr(obj, self.source),
model = typ.__name__,
id = obj.id)
return specs.somemethod()
Now:
class MyClass(db.Model):
somefield = db.Column(db.String(255))
someproperty = FieldProperty(MyField, source='somefield')
Or, if you prefer, you can create a base class or mixin for all your fields that adds a class method that does this for you:
class BaseField(object):
@classmethod
def make_property(cls, source):
return FieldProperty(cls, source)
And now:
class MyClass(db.Model):
somefield = db.Column(db.String(255))
someproperty = MyField.make_property('somefield')
Note the FieldProperty(object)
above. Descriptors have to be new-style classes, and they only work in new-style classes. In Python 3.x, new-style classes is all there is, but if you're using 2.x, every time you define a class with no base class, you get a old-style class. This is just one of the many reasons you don't want an old-style class; they also handle some special methods wrong, break multiple inheritance, make you look like a retro hipster, and sneak into your room and steal money out of your wallet while you sleep.
Upvotes: 1