1

I have two models,

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    surname = models.CharField(max_length=50)

    def __unicode__(self):
        return self.first_name

    def get_last_name(self):
        return self.last_name

    def get_full_name(self):
        return (self.first_name + self.surname + self.last_name)

class House(models.Model):
    name = models.CharField(max_length=50)
    persons = models.ManyToManyField(Person)
    house_number = models.CharField(max_length=5)

    def __unicode__(self):
        return self.first_name

and the models are registered on the admin site.

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    pass

@admin.register(House)
class HouseAdmin(admin.ModelAdmin):
    pass

For the model Person, I want admin site to display the method get_full_name() instead of __unicode__(), and get_last_name on the ManyToManyField of the model House.

How can I make this work?

thanks

All Іѕ Vаиітy
  • 24,861
  • 16
  • 87
  • 111
  • Just to clarify, for `Person` you want `get_full_name()` in admin, but `first_name` everywhere else? – Mike Covington Nov 05 '15 at 20:44
  • @MikeCovington, for the `person`, I want the person management url, `/admin/app/person` to display `get_full_name()`, and `get_last_name` on the `ManyToManyField` of Model `House` and `first_name` everywhere else. – All Іѕ Vаиітy Nov 05 '15 at 20:50

2 Answers2

2

To get the PersonAdmin to use get_full_name, just use get_full_name in list_display

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    list_display = ['get_full_name']

To customize the way that a person is displayed in a many to many field, override the label_from_instance method.

from django.forms import ModelMultipleChoiceField

class PersonLastNameChoiceField(ModelMultipleChoiceField):
    def label_from_instance(self, obj):
        return obj.get_last_name

Define a model form that uses your custom field,

class HouseForm(forms.ModelForm):
    persons = models.PersonLastNameChoiceField(Person.objects.all())

then use the model form in your model admin.

@admin.register(House)
class HouseAdmin(admin.ModelAdmin):
    form = HouseForm
Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • where should I place `PersonLastNameChoiceField` ? – All Іѕ Vаиітy Nov 06 '15 at 10:03
  • Wherever you want. Of you only use it in the model admin, then `admin.py` is fine. If you reuse it somewhere else, then you might want to have a separate module e.g. `fields.py`, and import it. – Alasdair Nov 06 '15 at 10:57
1

Read abount Proxy Models. A typical usecase for proxy models is to overwrite the Python behavior of a model, by changing its default manager or class methods.

class PersonAdmin(Person):
    class Meta:
        proxy = True
    def __unicode__(self):
        return self.get_full_name()

For more read this: Multiple ModelAdmins/views for same model in Django admin

Community
  • 1
  • 1
Tomasz Jakub Rup
  • 10,502
  • 7
  • 48
  • 49