9

I'm creating models, where each model should be related with a user, like this:

class Item(models.Model):
    user = models.ForeignKey(User)

But then in the Django Admin, for an Item, it shows a select field with all the users listed by their usernames. In addition to their usernames, I also need to display each user's first_name and last_name.

How can all three fields be displayed together within that select list in the Django Admin interface?

Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
rush
  • 2,484
  • 2
  • 19
  • 31

2 Answers2

19

You need to create custom Form for this and set form attribute in your ModelAdmin.

In that Form you will need to override form field type of user field on model to custom ModelChoiceField.

ModelChoiceField has a method called label_from_instance, you need to override that to get full name.

Example code

######################################
## models.py ##
######################################

from django.db import models
from django.contrib.auth.models import User

class Item(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField("name", max_length=60)

    def __unicode__(self):
        return self.name

######################################
## forms.py ##
######################################

from django import forms
from django.contrib.auth.models import User

from .models import Item


class CustomUserChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, obj):
         return obj.get_full_name()


class ItemForm(forms.ModelForm):
    user = CustomUserChoiceField(queryset=User.objects.all())

    class Meta:
        model = Item

######################################
## admin.py ##
######################################

from django.contrib import admin

from .models import Item
from .forms import ItemForm


class ItemAdmin(admin.ModelAdmin):
    form = ItemForm


admin.site.register(Item, ItemAdmin)

Source Code Reference

https://github.com/django/django/blob/1.4.5/django/forms/models.py#L948

Related Questions

  1. Django admin - change ForeignKey display text
  2. Django forms: how to dynamically create ModelChoiceField labels
  3. Change Django ModelChoiceField to show users' full names rather than usernames
  4. Django show get_full_name() instead or username in model form
  5. django: customizing display of ModelMultipleChoiceField
  6. django how to display users full name in FilteredSelectMultiple
  7. Django ModelChoiceField drop down box custom population
  8. customize select in django admin
  9. Use method other than unicode in ModelChoiceField Django
Community
  • 1
  • 1
pankaj28843
  • 2,458
  • 17
  • 34
  • 1
    Thank you for the answer. The last line has a typo I think. It should be "admin.site.register(Item, ItemAdmin)". – mp31415 Feb 27 '14 at 21:28
2

Django uses unicode(obj) (or the related function, str(obj)) in a number of places. Most notably, to display an object in the Django admin site and as the value inserted into a template when it displays an object.

Please see __unicode__ from https://docs.djangoproject.com/en/dev/ref/models/instances/

You can change __unicode__ method of User class. See below example codes.

from django.db import models
from django.contrib.auth.models import User

def myunicode(self):
    return self.get_full_name()

# Create your models here.
class Item(models.Model):
    User.__unicode__ = myunicode
    user = models.ForeignKey(User)
    name = models.CharField("name", max_length=60)

    def __unicode__(self):
        return self.name
Wonil
  • 6,364
  • 2
  • 37
  • 55
  • True, but in the case of a selection list generated for a `models.ForeignKey(User)`, the `unicode` function being called is the one for the `User`, so you still get a list of usernames. – Mike DeSimone May 04 '13 at 05:51
  • Yes. but, how about change User class's `__unicode__` method to my own at runtime? Please see my updated answer with example. – Wonil May 04 '13 at 09:55
  • It's risky. Since that's part of Django itself, and other apps can use it, you might get unexpected behavior from the other apps which expect `unicode` to return the username. The custom form keeps the change confined to just the part that needs it. BTW, you could also do `User.__unicode__ = lambda s: s.get_full_name()`. – Mike DeSimone May 04 '13 at 23:29