Skip to main content
 首页 » 编程设计

python之如何从 Django Admin 中的外键动态访问字段

2024年08月29日29bhlsheji

所以我有这样的模型:

class Celebrity(models.Model): 
    #30+ fields here ... 
 
class HoneyBadger(models.Model): 
    name = models.CharField(max_length=10) 
    celebrity_owner = models.ForeignKey(Celebrity) 

现在我希望 HoneyBadger 的管理界面显示该生物的名称以及名人所有者字段。

我知道标准的建议是做这样的事情:

class HoneyBadger(models.Model): 
    name = models.CharField(max_length=10) 
    celebrity_owner = models.ForeignKey(Celebrity) 
 
    def owner_birth_date(self): 
        return self.celebrity_owner.birth_date 
    #And so on for every other field in celebrity_owner 

然后在管理中引用这些方法。

相反,我想要一种方法来省去所有的输入工作!

这是我第一次尝试懒惰的捷径:

class HoneyBadger(models.Model): 
    name = models.CharField(max_length=10) 
    celebrity_owner = models.ForeignKey(Celebrity) 
 
    def __getattr__(self, name): 
        """Dynamically make derived fields for celebrity_owner fields so I don't have to type out""" 
        field_lookup_prefix = 'celebrity_owner_field_' 
        if name.startswith(field_lookup_prefix): 
            field_name = name[len(field_lookup_prefix):] 
            def wrapper(*args, **kwargs): 
                return getattr(self.celebrity_owner, field_name) 
            return wrapper 
        else: 
            raise AttributeError('%s not found' % name) 

当我在 shell 中运行它时它确实有效,但 Django 管理员不喜欢它。我收到此错误:

ImproperlyConfigured at /admin/tracker/ 
 
HoneyBadgerAdmin.list_display[5], 'celebrity_owner_field_birth_date' is not a callable or an attribute of 'HoneyBadgerAdmin' or found in the model 'HoneyBadger'. 

有谁知道我如何让我的代码与管理员一起工作,或者是否有另一种方法可以节省为每个名人字段键入方法? (也许是某种运行时猴子补丁?)

请您参考如下方法:

有两种可能的解决方法来实现您想要的。

  1. 在 HoneyBadger Admin 中提供指向 Celebrity 对象的链接:

    def celebrity_link(self): 
        return '<a href="%s">%s</a>' % (reverse('admin:appname_celebrity_change',args=(self.celebrity_owner.id,)), self.celebrity_owner.celeb_name) 
     
    celebrity_link.allow_tags = True 
    celebrity_link.short_description = u'Celebrity' 
     
    class HoneyBadgerAdmin(admin.ModelAdmin): 
        list_display = [..., celebrity_link, ...] 
    
  2. 下一个解决方案有点复杂,但可以满足我们的要求:定义您的自定义管理模板。基本上从 django 源代码复制更改表单并添加自定义代码以显示名人信息。看这个documentation .