在Django管理站点中,如何通过内联访问模型属性?

时间:2015-10-06 14:41:50

标签: python django

models.py:

class Player(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField(max_length=50)

class Tournament(models.Model):
    name = models.CharField(max_length=50)

class TournamentPlayer(models.Model):
    tournament = models.ForeignKey(Tournament)
    player = models.ForeignKey(Player)
    paid = models.BooleanField()

    def player_email(self):
        return self.player.email

admin.py:

class TournamentPlayerInline(admin.TabularInline):
    model = TournamentPlayer
    fields = ('player', 'paid', 'player_email')

@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
    inlines = [TournamentPlayerInline]

我有一个内联问题。当我在管理站点中召开锦标赛时,我可以看到哪些玩家正在进行,以及他们是否付费。我还想显示播放器中包含的额外信息,例如电子邮件地址。

在TournamentPlayerInline中,我认为我可以使用fields = ('player', 'paid', 'player_email'),但我得到 FieldError:为TournamentPlayer指定的未知字段(player_email)

我也试过了fields = ('player', 'paid', 'player__email'),但我得到了针对TournamentPlayer 指定的 FieldError:未知字段(player__email)。

如果我将player_emailfields移至readonly_fields,我就不会再收到错误,但也不会显示播放器电子邮件。

这就是我所追求的:

enter image description here

如何从TournamentPlayerInline访问播放器属性?

Django 1.8.4

3 个答案:

答案 0 :(得分:6)

猴子的答案几乎是正确的。您必须进行的唯一更改是 admin.py ,而且只是向'player_email'fields添加readonly_fields。更改'player_email'fields的位置将允许您按照示例进行排序。

class TournamentPlayerInline(admin.TabularInline):
    model = TournamentPlayer
    fields = ('player', 'player_email', 'paid',)
    readonly_fields = ('player_email',)

@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
    inlines = [TournamentPlayerInline]

答案 1 :(得分:1)

如果您不需要从内联中编辑player_email,则可以使用readonly_fields变量完成此操作:

class TournamentPlayerInline(admin.TabularInline):
    model = TournamentPlayer
    fields = ('player', 'paid')
    readonly_fields = ('player_email',)

@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
    inlines = [TournamentPlayerInline]

答案 2 :(得分:0)

作为替代方案,您不必在模型中定义自定义属性,如果您不直接使用它,并且只想在管理中查看它 - 您可以通过mixin在内联中创建它:

models.py

class Player(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField(max_length=50)

class Tournament(models.Model):
    name = models.CharField(max_length=50)

class TournamentPlayer(models.Model):
    tournament = models.ForeignKey(Tournament)
    player = models.ForeignKey(Player)
    paid = models.BooleanField()

admin.py

class PlayerEmailMixin(object):
    def player_email(self, obj):
        return obj.player.email

    player_email.short_description = "Player Email"

class TournamentPlayerInline(PlayerEmailMixin, admin.TabularInline):
    model = TournamentPlayer
    fields = ('player', 'player_email', 'paid', )
    readonly_fields = ('player_email',)

@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
    inlines = [TournamentPlayerInline]

您也可以通过这种方式将其设为mailto:

class PlayerEmailMixin(object):
    def player_email(self, obj):
        return '<a href="mailto:{0}"><strong>{0}</strong></a>'.format(obj.player.email)

    player_email.short_description = "Player Email"
    player_email.allow_tags = True

这在Django 1.9.5中已知有效。