0

I'd like to create a Model Class for an User. The data of the user are stored in an document based database like couchdb or mongodb. The class User should have an decorator and the fields ind the db are accessible over not really existing class attributes. For example

@DocumentDB()
class User(object):
    def doSomething(self):
        pass
    def doSomethingElse(self):
        pass

u = User('thisIsAUniqUserId')
print u.emailAddress
print u.lastName

I've played around with python decorators. Manipulating existing functions is not a big thing but how can i catch the call for not existing getters/setters to create transparent access to db values trough the instance of the object?

Thomas Spycher
  • 956
  • 13
  • 32
  • 1
    Not sure if I have understood your question correctly (mainly the decorator part), but I think this is what you might be looking for - http://docs.python.org/2/reference/datamodel.html#customizing-attribute-access – naiquevin Jan 15 '13 at 08:24

4 Answers4

2

You need to implement the __getattr__(self, name) method.

Ber
  • 40,356
  • 16
  • 72
  • 88
1

Access to an object's attributes is governed by the getattr/setattr/delattr/getattribute mechanism.

XORcist
  • 4,288
  • 24
  • 32
1

Django uses metaclasses to dynamically create models. While your requirements are a little different, the same technique will work (probably better then decorators).

You can read more about Python metaclasses on Stackoverflow.

Community
  • 1
  • 1
jimhark
  • 4,938
  • 2
  • 27
  • 28
  • It's an interesting topic! Didn't know that either... I'm not really sure if this fits perfect to my needs. Django does not directly support DocumentBased Databases. This technique works well if you initially know which fields in your database are available... In my case every document can be slightly different to each other and due to speed improvements i think this "Proxy-Decorator" Idea could be a better solution. I might be wrong? – Thomas Spycher Jan 16 '13 at 06:43
  • No, I think your're right. After I posted my answer I realized that couchdb/mongodb were more flexible (less structured) than a SQL database. Therefore @Ber's answer is probably the best and I just up voted it. Good luck. – jimhark Jan 16 '13 at 08:42
0

I think i found a solution based on your suggestions:

def DocumentDB(object):
    class TransparentAttribute:
        def __init__(self, *args, **kargs):                 
            self.wrapped = object(*args, **kargs)
        def __getattr__(self, attrname):
            return "Any Value"
    return TransparentAttribute

@DocumentDB
class User(object):
    def doSomething(self):
        pass
    def doSomethingElse(self):
        pass

u = User()
print u.emailAddress
print u.lastName

It works, but is it the most pythoniastic way?

Thomas Spycher
  • 956
  • 13
  • 32
  • What you get by using DocumentDB is a wrapped class. So 'TransparentAttribute' is a misnomer. An attribute is something you look up on a python object (be it a class or an instance thereof). Idiomatically speaking, looking up an attribute that is not explicitly defined is against the 'explicit is better than implicit' mantra. – XORcist Jan 15 '13 at 09:40
  • I think you could just add the `__getattr__()` method to your `User()` class. I don't quite see the need for the wrapper class. – Ber Jan 16 '13 at 08:27