Python 当调试为False时,管理中指向Foreignkey的链接会导致AttributeError
我在models.py文件中使用了以下代码: 创建指向foreignkey的超链接Python 当调试为False时,管理中指向Foreignkey的链接会导致AttributeError,python,django,django-admin,foreign-keys,Python,Django,Django Admin,Foreign Keys,我在models.py文件中使用了以下代码: 创建指向foreignkey的超链接 class ModelAdminWithForeignKeyLinksMetaclass(MediaDefiningClass): def __getattr__(cls, name): def foreign_key_link(instance, field): target = getattr(instance, field) re
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
class ModelAdminWithForeignKeyLinksMetaclass(MediaDefiningClass):
def_u_getattr__(cls,名称):
def外键链接(实例,字段):
target=getattr(实例,字段)
返回u'%(
目标。_meta.app_标签,目标。_meta.module_名称,target.id,unicode(目标))
如果名称[:8]=“链接到”:
方法=部分(外键链接,字段=名称[8:])
方法。\名称\名称=name[8:]
method.allow_tags=True
setattr(cls、名称、方法)
返回getattr(cls,名称)
提高属性错误
在admin.py list_display中,我将link_添加到每个字段的开头,我想要一个foreignkey链接。这工作得非常好,但是当我关闭调试时,会出现属性错误。有什么建议吗?我偶然发现了完全相同的问题,幸运的是,我已经解决了 原始解决方案(您使用的解决方案)来自,我的解决方案基于此:
class ForeignKeyLinksMetaclass(MediaDefiningClass):
def __new__(cls, name, bases, attrs):
new_class = super(
ForeignKeyLinksMetaclass, cls).__new__(cls, name, bases, attrs)
def foreign_key_link(instance, field):
target = getattr(instance, field)
return u'<a href="../../%s/%s/%d/">%s</a>' % (
target._meta.app_label, target._meta.module_name,
target.id, unicode(target)
)
for name in new_class.list_display:
if name[:8] == 'link_to_':
method = partial(foreign_key_link, field=name[8:])
method.__name__ = name[8:]
method.allow_tags = True
setattr(new_class, name, method)
return new_class
class ForeignKeyLinksMetaclass(MediaDefiningClass):
定义(cls、名称、基数、属性):
新类=超级(
ForeignKeyLinksMetaclass,cls)。\uuuu新建(cls,名称,基础,属性)
def外键链接(实例,字段):
target=getattr(实例,字段)
返回u'%(
目标。_meta.app_标签,目标。_meta.module_名称,
target.id,unicode(目标)
)
对于“新建类列表”显示中的名称:
如果名称[:8]=“链接到”:
方法=部分(外键链接,字段=名称[8:])
方法。\名称\名称=name[8:]
method.allow_tags=True
setattr(新类、名称、方法)
返回新的\u类
好的,您只需要用上面的模型替换原始模型AdminWithForeignKeyLinksMetaClass
然而,这并不是结束。最有趣的部分是为什么原始解决方案会导致问题。这个问题的答案是(第31行)和(第244行)
当DEBUG开启时,Django尝试验证所有注册的ModelAdmins(第一个链接)。cls有一个类SomeAdmin(即其元类的实例)。当调用hasattr时,python会尝试在类SomeAdmin或它的一个超类中查找属性字段。因为这是不可能的,所以会调用其类(即SomeAdmin的元类)的_getattr _uu,其中会向类SomeAdmin添加一个新方法。因此,在呈现界面时,SomeAdmin已经打了补丁,Django能够找到所需的字段(第二个链接)
如果DEBUG为False,Django将跳过验证。当接口呈现为Django时,Django尝试查找一个字段(同样是第二个链接),但这次SomeAdmin没有修补,而且model_admin不是类SomeAdmin,它是它的实例。因此,试图在model_admin中找到属性名,python无法做到这一点,也无法在其类(SomeAdmin)以及任何超类中找到它,因此引发了一个异常。我使用stepank的实现,但不得不稍微修改它以适应我的用例 我基本上只是添加了对'ModelAdmin.readonly_fields'和'ModelAdmin.fields'的支持,以支持'link_to_'-语法 对链接创建的轻微更改还允许我支持指向不同APP.Model的链接,在我的例子中是内置的django.contrib.auth.models.user 感谢stepank和Itai Tavor的出色工作 我希望这对其他人有用
默认_LOGGER_名称在my settings.py中定义,我在大多数日志记录中都使用它。如果没有定义它,则在使用以下代码时会出现错误。您可以在settings.py中定义自己的默认\u LOGGER\u名称(它只是一个简单的字符串),也可以在下面的代码中删除对记录器的所有引用
'''
Created on Feb 23, 2012
@author: daniel
Purpose: Provides a 'link_to_<foreignKeyModel>' function for ModelAdmin
implementations. This is based on the following work:
original: http://stackoverflow.com/a/3157065/193165
fixed original: http://stackoverflow.com/a/7192721/193165
'''
from functools import partial
from django.forms import MediaDefiningClass
import logging
from public.settings import DEFAULT_LOGGER_NAME
logger = logging.getLogger(DEFAULT_LOGGER_NAME)
class ForeignKeyLinksMetaclass(MediaDefiningClass):
def __new__(cls, name, bases, attrs):
new_class = super(
ForeignKeyLinksMetaclass, cls).__new__(cls, name, bases, attrs)
def foreign_key_link(instance, field):
target = getattr(instance, field)
ret_url = u'<a href="../../%s/%s/%d/">%s</a>' % (
target._meta.app_label, target._meta.module_name,
target.id, unicode(target)
)
#I don't know how to dynamically determine in what APP we currently
#are, so this is a bit of a hack to enable links to the
#django.contrib.auth.models.user
if "auth" in target._meta.app_label and "user" in target._meta.module_name:
ret_url = u'<a href="/admin/%s/%s/%d/">%s</a>' % (
target._meta.app_label, target._meta.module_name,
target.id, unicode(target)
)
return ret_url
def _add_method(name):
if name is None: return
if isinstance(name, basestring) and name[:8] == 'link_to_':
try:
method = partial(foreign_key_link, field=name[8:])
method.__name__ = name[8:]
method.allow_tags = True
#in my app the "user" field always points to django.contrib.auth.models.user
#and I want my users to see that when they edit "client" data
#"Client" is another model, that has a 1:1 relationship with
#django.contrib.auth.models.user
if "user" in name[8:]:
method.short_description = "Auth User"
setattr(new_class, name, method)
except Exception, ex:
logger.debug("_add_method(%s) failed: %s" % (name, ex))
#make this work for InlineModelAdmin classes as well, who do not have a
#.list_display attribute
if hasattr(new_class, "list_display") and not new_class.list_display is None:
for name in new_class.list_display:
_add_method(name)
#enable the 'link_to_<foreignKeyModel>' syntax for the ModelAdmin.readonly_fields
if not new_class.readonly_fields is None:
for name in new_class.readonly_fields:
_add_method(name)
#enable the 'link_to_<foreignKeyModel>' syntax for the ModelAdmin.fields
if not new_class.fields is None:
for name in new_class.fields:
_add_method(name)
return new_class
“”
创建于2012年2月23日
@作者:丹尼尔
用途:为ModelAdmin提供“链接到”功能
实现。这是基于以下工作:
原件:http://stackoverflow.com/a/3157065/193165
固定原件:http://stackoverflow.com/a/7192721/193165
'''
从functools导入部分
从django.forms导入MediaDefiningClass
导入日志记录
从public.settings导入默认\u记录器\u名称
logger=logging.getLogger(默认的记录器名称)
类别ForeignKeyLinksMetaclass(MediaDefiningClass):
定义(cls、名称、基数、属性):
新类=超级(
ForeignKeyLinksMetaclass,cls)。\uuuu新建(cls,名称,基础,属性)
def外键链接(实例,字段):
target=getattr(实例,字段)
ret_url=u'%(
目标。_meta.app_标签,目标。_meta.module_名称,
target.id,unicode(目标)
)
#我不知道如何动态确定我们当前使用的应用程序
#是的,所以启用到
#django.contrib.auth.models.user
如果在target.\u meta.app.\u标签中有“auth”,在target.\u meta.module.\u名称中有“user”:
ret_url=u'%(
目标。_meta.app_标签,目标。_meta.module_名称,
target.id,unicode(目标)
)
返回ret_url
定义添加方法(名称):
如果name为None:返回
如果isinstance(名称、基串)和name[:8]=“链接到”:
尝试:
方法=部分(外键链接,字段=名称[8:])
方法。\名称\名称=name[8:]
method.allow_tags=True
#在我的应用程序中,“用户”字段始终指向django.contrib.auth.models.user
#我希望我的用户在下载时看到这一点