【问题标题】:How to reference model joined across foreign key in django admin如何在 django admin 中跨外键引用模型
【发布时间】:2015-03-26 10:21:32
【问题描述】:

我有一个 django 1.6 应用程序,其中包含以下内容(为清晰起见进行了修剪) 定义的类。 User 是标准的 django.contrib.auth 用户类。

class Event(models.Model):
    user = models.ForeignKey(User, related_name='events')
    name = models.CharField(max_length=64)


class Profile(models.Model):
    user = models.ForeignKey(User, related_name='aprofile')


class MemberProfile(Profile):
    pass

这是我的管理类:

class ProfileAdmin(ModelAdmin):
    model = Profile
    fields = ('user', )


class MemberProfileAdmin(ModelAdmin):
    model = MemberProfile
    fields = ('user', )
    readonly_fields = ('user', )

我想做的是显示给定成员的所有事件的只读列表,或者至少是个人资料。当然,跨用户外键加入似乎是要走的路,但我对如何实现这一点持空白。以下是迄今为止的尝试总结。

在直接引用用户字段的 Event 类上定义一个内联管理员,并将其添加到 ProfileAdmin:

class EventInlineAdmin(TabularInline):
    model = Event
    fk_name = 'user'    # Fails - fk_name 'user' is not a ForeignKey to <class 'solo365.solo_profile.models.profile.Profile'>

...嗯,不,肯定不是。但是我们的 User 有一个 'aprofile' 字段,所以...

class EventInlineAdmin(TabularInline):
    model = Event
    fk_name = 'user__aprofile'    # Fails - EventInlineAdmin.fk_name' refers to field 'user__aprofile' that is missing from model 'admin_fk_test.Event'.

好的,这些字段看起来应该同步,但也许我们需要更积极一点:

class EventInlineAdmin(TabularInline):
    model = Event
    fk_name = 'user__aprofile__pk'    # Fails - 'EventInlineAdmin.fk_name' refers to field 'user__aprofile__pk' that is missing from model 'admin_fk_test.Event'.

我也尝试过使用内联和常规模型管理员中的 formfield_for_foreignkey() 和朋友,但如果 fk_name 没有有效值,这些方法永远不会被调用。

然后我考虑尝试直接从个人资料的用户访问事件字段:

class ProfileAdmin(ModelAdmin):
    model = Profile
    fields = ('user', 'user__events')  # Fails - Unknown field(s) (user__events) specified for Profile. Check fields/fieldsets/exclude attributes of class ProfileAdmin.

自定义 formfield_for_foreignkey() 方法怎么样?可悲的是,除了“用户”字段之外,它永远不会被调用。我也考虑过自定义 get_formsets() 方法,但坦率地说,我不确定在没有有效的 EventInlineAdmin 的情况下如何使用它。

我当然可以定义一个自定义字段,它简单地连接所有事件并将其作为字符串返回,但理想情况下,我更喜欢功能齐全的内联(甚至是只读)而不是一个块 o' 文本. IOW 这样的自定义字段将有一个方法(理想情况下)将返回内联表单,而无需任何类型的自定义模板、allow_tags 设置等。

我注定要为 Profile 管理类创建一个完全自定义的表单吗?或者有没有一种简单的方法来完成我正在尝试做的事情,而我只是错过了?

更新:

如果提供的解决方案适用于 MemberProfileAdmin 类,而不仅仅是 ProfileAdmin 类,则奖励积分。

【问题讨论】:

  • 我会亲自为每一个覆盖 change_form.html。所以在你的模板文件夹/templates/admin/AppName/modelname/change_form.html
  • 感谢您的回复。我也想到了这一点,只是希望尽可能避免使用任何类型的自定义表单或模板。

标签: django django-admin foreign-keys


【解决方案1】:

UserProfile 之间的关系应该是1:1 关系,这将允许通过user__aprofile 进行引用。否则,外键的反向关系就是一个查询集,因为一个外键可以分配给多个实例。这可能是您的代码失败的原因。

改成:

class Profile(models.Model):
    user = models.OneToOneKey(User, related_name='aprofile')

这有点像使用ForeignKey(unique=True)

要了解属性,在相关模型实例上调用 dir(model_instance) 可能会有所帮助,或者在 Django shell (./manage.py shell) 中尝试一下。

此外,我还经历过分配自定义related_name 可能会更令人困惑,就像您希望通过查看相关名称获得一个配置文件但实际上会返回一个查询集的情况一样。 在这种情况下,生成的名称将是profile_set,您必须调用profile_set.all()profile_set.values() 才能获得一些实际的配置文件。

【讨论】:

  • 感谢您的回复。我已经从那个项目继续前进,所以无法测试代码,但觉得你应该为这个尝试投赞成票:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-30
  • 2013-09-29
  • 2018-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多