如何在django admin中引用跨外键加入的模型

时间:2015-01-27 17:40:45

标签: django django-admin foreign-keys

我有一个带有以下的django 1.6应用程序(为了清晰起见而修剪) 课程定义。用户是标准的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'>

......好吧,不,肯定不是。但我们的用户有一个'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,我不知道如何使用它。

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

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

更新

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

1 个答案:

答案 0 :(得分:2)

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

将其更改为:

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()以获取一些实际的个人资料。