He visto ejemplos en línea de personas que usan __getattr__
con modelos de Django, pero cada vez que lo intento obtengo errores. (Django 1.2.3)¿Por qué no puedo usar __getattr__ con los modelos de Django?
No tengo ningún problema cuando estoy usando __getattr__
en objetos normales. Por ejemplo:
class Post(object):
def __getattr__(self, name):
return 42
funciona bien ...
>>> from blog.models import Post >>> p = Post() >>> p.random 42
Ahora, cuando lo intento con un modelo de Django:
from django.db import models
class Post(models.Model):
def __getattr__(self, name):
return 42
y probarlo en el intérprete:
>>> from blog.models import Post >>> p = Post() ERROR: An unexpected error occurred while tokenizing input The
following 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 signal
TypeError: 'int' object is not callable
¿Alguien puede explicar lo que está pasando? g on?
EDIT: Yo podría haber sido demasiado abstracto en los ejemplos, he aquí algo de código que está más cerca de lo que en realidad usaría en el sitio web:
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...
Mientras podría crear una propiedad para cada atributo de la clase Post, que daría lugar a una gran cantidad de duplicación de código. Además, eso significaría que cada vez que agregue o edite un atributo de la clase Post, tendría que recordar hacer el mismo cambio en la clase CuratedPost, que parece una receta para la descomposición del código.
¿es realmente "return self.post.name"? Debería ser "return getattr (self.post, name)" –
De hecho, eso es lo que el código debería ser – Joshmaker