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