I have used the following code in my models.py file:
Create hyperlink to foreignkey
class ModelAdminWithForeignKeyLinksMetaclass(MediaDefiningClass):
def __getattr__(cls, name):
def foreign_key_link(instance, field):
target = getattr(instance, field)
return u'<a href="../../%s/%s/%s">%s</a>' % (
target._meta.app_label, target._meta.module_name, target.id, unicode(target))
if name[:8] == 'link_to_':
method = partial(foreign_key_link, field=name[8:])
method.__name__ = name[8:]
method.allow_tags = True
setattr(cls, name, method)
return getattr(cls, name)
raise AttributeError
In admin.py list_display I’ve added link_to to the beginning of each field I want a foreignkey link on. This works really well however when I turn debug off I get an attribute error. Any suggestions?
I stumbled on exactly the same problem, luckily, I’ve fixed it.
The original solution (the one you used) comes from this question, my solution is based on it:
Well, the only thing you need is to replace the original ModelAdminWithForeignKeyLinksMetaclass with the one above.
However, it’s not the end. The most interesting part is why the original solution causes problems. The answer to this question lies here (line 31) and here (line 244).
When DEBUG is on Django tries to validate all registered ModelAdmins (first link). There cls is a class SomeAdmin (i.e. an instance of its metaclass). When hasattr is called, python tries to find an attribute field in class SomeAdmin or in one of its super classes. Since it is impossible, __getattr__ of its class (i.e. SomeAdmin‘s metaclass) is called, where a new method is added to class SomeAdmin. Hence, when it comes to rendering the interface, SomeAdmin is already patched and Django is able to find the required field (second link).
When DEBUG is False, Django skips the validation. When the interface is rendered Django tries to find a field (again, second link), but this time SomeAdmin is not patched, moreover model_admin is not class SomeAdmin, it is its instance. Thus, trying to find an attribute name in model_admin, python is unable to do this, neither it is able to find it in its class (SomeAdmin) as well as in any of its super classes, so an exception is raised.