在 Django 管理站点中,如何通过内联访问模型属性?
Posted
技术标签:
【中文标题】在 Django 管理站点中,如何通过内联访问模型属性?【英文标题】:In the Django Admin Site, how can I access model properties through an Inline? 【发布时间】:2016-01-03 12:58:02 【问题描述】: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]
我有一个内联问题。当我在管理站点中启动锦标赛时,我可以看到哪些玩家参加了比赛,以及他们是否付费。我还想显示 Player 中包含的额外信息,例如电子邮件地址。
在 TournamentPlayerInline 中,我认为我可能能够摆脱 fields = ('player', 'paid', 'player_email')
,但我得到 FieldError: Unknown field(s) (player_email) specified for TournamentPlayer。
我也试过fields = ('player', 'paid', 'player__email')
,但我得到FieldError: Unknown field(s) (player__email) specified for TournamentPlayer。
如果我将player_email
从fields
移动到readonly_fields
,我将不再收到错误消息,但也不会显示玩家电子邮件。
这就是我所追求的:
如何从 TournamentPlayerInline 访问 Player 属性?
Django 1.8.4
【问题讨论】:
您是否尝试过将player_email
设为@property
?您也可以使用双下划线将其设为 fields = ('player', 'paid', 'player__email')
以表示外键关系。
我在def player_email(self):
上方添加了@property,没有效果。也试过 player__email 没有效果。
嗯...查看此问题中显示的管理员定义:***.com/questions/163823/…
在def player_email
之后添加了player_email.admin_order_field = 'player__email'
,没有效果。
您希望player_email
在管理员中可编辑吗?否则,您只需将其从 fields
中删除并将其添加到 readonly_fields
即可。
【参考方案1】:
Monkey 的回答几乎是正确的。您需要做的唯一更改是您的admin.py,它只是将'player_email'
添加到fields
和readonly_fields
。在fields
中更改'player_email'
的位置将允许您按照您的示例对其进行排序。
class TournamentPlayerInline(admin.TabularInline):
model = TournamentPlayer
fields = ('player', 'player_email', 'paid',)
readonly_fields = ('player_email',)
@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
inlines = [TournamentPlayerInline]
【讨论】:
【参考方案2】:如果您不要求可以从内联编辑 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]
【讨论】:
虽然这不会产生错误,但在查看锦标赛时也不会显示玩家电子邮件。这就是我所追求的:i.imgur.com/IPIZNId.png【参考方案3】:作为替代方案,如果您不直接使用它,则不必在模型中定义您的自定义属性,而只想在管理员中查看它——您可以通过 mixin 在 Inline 中创建它:
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 URI:
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 中是已知的
【讨论】:
以上是关于在 Django 管理站点中,如何通过内联访问模型属性?的主要内容,如果未能解决你的问题,请参考以下文章
管理站点中的 Django DateTimeField 编辑
如何在 django 管理页面上创建锚点以自动从 url 向下滚动到内联或字段