Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialqlpxjevhuv
10,503 PointsUsing a ForeignKey to pull author's name
I am having trouble figuring out how to get the author's full name instead of their username when linking a Post to the User. Currently, it returns the username, which I presume has something to do with the User's str method. I found out that I can add an 'if int' statement to it which would return a formatted string with the author's full name, but is there a more preferred way of doing this?
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)
Edit:
# models
class MyUser(AbstractBaseUser):
username = ...
first_name = ...
last_name = ...
__str__(self):
return self.username
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)
3 Answers
Chris Freeman
Treehouse Moderator 68,425 PointsThe ForeignKey is used to relate one model to another, it's not used to access attributes on other models.
In your case, with a given Post instance, say post
, you can use one of the built-in methods to User
to get the full name:
author_fullname = post.author.get_full_name()
See link for other methods available.
qlpxjevhuv
10,503 PointsI'm still having issues with this :\
# models
class MyUser(AbstractBaseUser):
username = ...
first_name = ...
last_name = ...
__str__(self):
return self.username
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)
# forms
from django.forms import ModelChoiceField
from django import forms
from blog.models import MyUser, Post
class UserModelChoiceField(ModelChoiceField):
"""
Custom ModelChoiceField for representing User select boxes in Admin
"""
def label_from_instance(self, obj):
return "{}".format(obj.get_full_name())
class PostAdminForm(forms.ModelForm):
author = UserModelChoiceField(MyUser.objects.all()
.order_by('last_name', 'first_name'))
class Meta:
model = Post
fields = '__all__'
# admin
from blog.models import MyUser, Post
class PostAdmin(admin.ModelAdmin):
form = PostAdminForm
list_display = ['title', 'author', ]
list_filter = ['author', ]
def save_model(self, request, obj, form, change):
if getattr(obj, 'author', None) is None:
obj.author = request.user
obj.save()
admin.site.register(Post, PostAdmin)
Here is a screenshot:
http://imgur.com/v7DfyGU Top image is current result. Bottom image is desired result.
[MOD: made image inline -cf]
Chris Freeman
Treehouse Moderator 68,425 PointsWhere is the "title
" field shown in the display_list
coming from?
Chris Freeman
Treehouse Moderator 68,425 PointsThough the Django docs mention ForeignKeys will be displayed as their __str__
value, would it work to add an additional field instead of trying to replace the default __str__
value? Based on code examples from the same link, perhaps you can try adding an additional field.
# Modify the class
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)
# Add helper function for Admin display
def author_full_name(self):
return self.author. get_full_name()
author_full_name.short_description = 'Full Name'
# In admin.py
class PostAdmin(admin.ModelAdmin):
list_display = ('author_full_name', 'author')
qlpxjevhuv
10,503 Pointsqlpxjevhuv
10,503 PointsI'm not sure I understand. With the code above, when I select the author for the blog post in my admins panels (using django), the names that appear are usernames - instances of the User model. Instead of having the usernames come up, I'm trying to get their actual names. I think the reason the usernames are coming up is because of the str returning self.username. So I think I just have to edit that to return the full name instead and that's it?
Chris Freeman
Treehouse Moderator 68,425 PointsChris Freeman
Treehouse Moderator 68,425 PointsSorry. I didn't realize you were referring to the Django admin views. These views are not trivial to modify but it can be done. I found this blog post with instructions: Pretty options for Django Authuser
qlpxjevhuv
10,503 Pointsqlpxjevhuv
10,503 PointsOkay, it is working properly now on the form, but for the PostAdmin in admin.py, the list_display is still referring to the Post model's author attribute which continues to return the username. So it seems I have to make a modification somewhere with the models. I presume the only way is to change the
__str__
on the User model?Chris Freeman
Treehouse Moderator 68,425 PointsChris Freeman
Treehouse Moderator 68,425 PointsOverwriting the
__str__
method for User model in the core code can be troublesome. The better approach is to follow the instructions in the blog post to create a new AdminForm which calls custom UserModelChoiceField which has the format you are looking for. The blog uses "full_name (username)
" format.