| 1 | class ForeignKey:
|
|---|
| 2 | fkeys_to_name = {} # Keyed by object's id
|
|---|
| 3 | def __init__(self, otherclass):
|
|---|
| 4 | self.otherclass = otherclass
|
|---|
| 5 | self.default_name = self.otherclass.__name__.lower()
|
|---|
| 6 | self.name = None # Will be set later
|
|---|
| 7 |
|
|---|
| 8 | # Keep a reference to this instance around
|
|---|
| 9 | ForeignKey.fkeys_to_name[id(self)] = self
|
|---|
| 10 |
|
|---|
| 11 | class ModelBase(type):
|
|---|
| 12 | # Metaclass for Model objects
|
|---|
| 13 | def __new__(cls, name, bases, attrs):
|
|---|
| 14 | if not bases:
|
|---|
| 15 | return type.__new__(cls, name, bases, attrs)
|
|---|
| 16 | new_class = type.__new__(cls, name, bases, attrs)
|
|---|
| 17 | for name, obj in attrs.items():
|
|---|
| 18 | if isinstance(obj, ForeignKey):
|
|---|
| 19 | obj.name = name
|
|---|
| 20 | del ForeignKey.fkeys_to_name[id(obj)]
|
|---|
| 21 | # Now all named ForeignKeys are gone, only unnamed ones remain
|
|---|
| 22 | for fkey in ForeignKey.fkeys_to_name.values():
|
|---|
| 23 | fkey.name = fkey.default_name
|
|---|
| 24 | setattr(new_class, fkey.name, fkey)
|
|---|
| 25 | ForeignKey.fkeys_to_name = {} # Reset for next class
|
|---|
| 26 | return new_class
|
|---|
| 27 |
|
|---|
| 28 | class Model:
|
|---|
| 29 | __metaclass__ = ModelBase
|
|---|
| 30 |
|
|---|
| 31 | class One(Model):
|
|---|
| 32 | pass
|
|---|
| 33 |
|
|---|
| 34 | class Two(Model):
|
|---|
| 35 | pass
|
|---|
| 36 |
|
|---|
| 37 | class SampleRecord(Model):
|
|---|
| 38 | ForeignKey(One)
|
|---|
| 39 | ForeignKey(Two)
|
|---|
| 40 |
|
|---|
| 41 | if __name__ == '__main__':
|
|---|
| 42 | for name, val in SampleRecord.__dict__.items():
|
|---|
| 43 | print name, '=', val
|
|---|
| 44 | if isinstance(val, ForeignKey):
|
|---|
| 45 | print val, 'knows its name is', val.name
|
|---|