Why can't I use __getattr__ with Django models?
我在网上看到过一些人在使用django模型时使用
当我在普通对象上使用
1 2 3 | class Post(object): def __getattr__(self, name): return 42 |
工作很好…
1
2
3
4 >>> from blog.models import Post
>>> p = Post()
>>> p.random
42
号
现在,当我尝试使用Django模型时:
1 2 3 4 | from django.db import models class Post(models.Model): def __getattr__(self, name): return 42 |
号
在口译员身上进行测试:
1
2
3 >>> from blog.models import Post
>>> p = Post()
ERROR: An unexpected error occurred while tokenizing input Thefollowing traceback may be corrupted
or invalid The error message is: ('EOF
in multi-line statement', (6, 0))--------------------------------------------------------------------------- TypeError
Traceback (most recent call last)/Users/josh/project/
in ()/Users/josh/project/lib/python2.6/site-packages/django/db/models/base.pyc
in init(self, *args, **kwargs)
338 if kwargs:
339 raise TypeError("'%s' is an invalid keyword
argument for this function" %
kwargs.keys()[0])
--> 340 signals.post_init.send(sender=self.class,
instance=self)
341
342 def repr(self):/Users/josh/project/lib/python2.6/site-packages/django/dispatch/dispatcher.pyc
in send(self, sender, **named)
160
161 for receiver in self._live_receivers(_make_id(sender)):
--> 162 response = receiver(signal=self, sender=sender,
**named)
163 responses.append((receiver, response))
164 return responses/Users/josh/project/python2.6/site-packages/photologue/models.pyc
in add_methods(sender, instance,
signal, *args, **kwargs)
728 """
729 if hasattr(instance, 'add_accessor_methods'):
--> 730 instance.add_accessor_methods()
731
732 # connect the add_accessor_methods function to the
post_init signalTypeError: 'int' object is not
callable
号
有人能解释一下发生了什么事吗?
编辑:我可能在示例中过于抽象,下面是一些更接近我在网站上实际使用的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Post(models.Model): title = models.CharField(max_length=255) slug = models.SlugField() date_published = models.DateTimeField() content = RichTextField('Content', blank=True, null=True) # Etc... Class CuratedPost(models.Model): post = models.ForeignKey('Post') position = models.PositiveSmallIntegerField() def __getattr__(self, name): ''' If the user tries to access a property of the CuratedPost, return the property of the Post instead... ''' return self.post.name # Etc... |
虽然我可以为post类的每个属性创建一个属性,但这会导致大量代码重复。更进一步,这意味着每当我添加或编辑post类的属性时,我都必须记住对curatedpost类进行相同的更改,这看起来像是代码腐烂的秘诀。
用 getattr uu来照顾一个人。只有拦截你所知道的,让基地班级掌握你所不知道的。
第一步是,你能使用一个不动产吗?如果你想要一个"随机"的属性,42,这是非常安全的:
ZZU1
如果你想"random *"(like"random 1","random 34"等)做些什么,你就必须使用
1 2 3 4 5 | class Post(...): def __getattr__(self, name): if name.startswith("random_"): return name[7:] return super(Post, self).__getattr__(name) |
Django sends certain signals when the models a re first initiatized(IE,by loading up the shell)-by making it so calls to
如果你想这样做,也许你可以尝试这样做:
1 2 3 4 | def __getattr__(self, attr): if hasattr(self, attr): return super(MyModel, self).__getattr__(attr) return 42 |