Reputation: 4423
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]
I have an Inline question. When I pull up a Tournament in the Admin Site, I can see which players are going, and if they paid. I would also like to display extra information contained in Player, for example email address.
In TournamentPlayerInline I thought I might be able to get away with fields = ('player', 'paid', 'player_email')
but I get FieldError: Unknown field(s) (player_email) specified for TournamentPlayer.
I also tried fields = ('player', 'paid', 'player__email')
, but I get FieldError: Unknown field(s) (player__email) specified for TournamentPlayer.
If I move player_email
from fields
to readonly_fields
, I no longer get the error, but the player email also isn't displayed either.
This is what I'm after:
How can I access Player properties from TournamentPlayerInline?
Django 1.8.4
Upvotes: 9
Views: 7002
Reputation: 290
As an alternative, you do not have to define your custom property in your model if you're not using it directly, and just want to view it in admin -- you can create it in the Inline via a 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]
You could also make it a mailto URI this way:
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
This is known to work in Django 1.9.5
Upvotes: 0
Reputation: 120
Monkey's answer is almost correct. The only change you have to make is to your admin.py, and it's merely adding 'player_email'
to both fields
as well as readonly_fields
. Changing the position of 'player_email'
in fields
will allow you to order it as per your example.
class TournamentPlayerInline(admin.TabularInline):
model = TournamentPlayer
fields = ('player', 'player_email', 'paid',)
readonly_fields = ('player_email',)
@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
inlines = [TournamentPlayerInline]
Upvotes: 8
Reputation: 3077
If you do not require the player_email
to be editable from the inline, then you can accomplish this with the readonly_fields
variable:
class TournamentPlayerInline(admin.TabularInline):
model = TournamentPlayer
fields = ('player', 'paid')
readonly_fields = ('player_email',)
@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
inlines = [TournamentPlayerInline]
Upvotes: 1