| 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 |
|---|