Home > Mobile >  Django admin, return full name function to list_filter
Django admin, return full name function to list_filter

Time:07-15

So I made a model called Customers which has a first_name, a last_name, and a dob (aka Date of Birth).

I don't want to store the full_name in a field, I just want to be able to order the customers by their Full name, rather than either first_* or last_*.

I wanted to make a function in the model called getFullName, which returns the first and last name together, but Django threw an error saying getFullName does not refer to a field.

Any ideas on how I could fix that by avoiding having a full_name attr, which is being set on the save method?

I'm also using the default Django admin, just because I love it (especially with Django-jet).

edit: source as requested.

# models.py
class Customer(models.Model):
    first_name = models.CharField(max_length=100, blank=False, verbose_name="First name", null=True)
    last_name = models.CharField(max_length=100, blank=False, verbose_name="Last name", null=True)
    dob = models.DateField(verbose_name="Date of Birth", blank=False, null=True)

    def getFullName(self):
        return "%s %s" %(self.first_name, self.last_name)
    getFullName.short_description = "Full Name"

# admin.py
class CustomerAdmin(admin.ModelAdmin):
    # here would be the list_filter = ('getFullName',), which threw the mentioned error.
    # list_display = ('getFullName',) works just fine, but that is not what I want to achieve.
    pass

admin.site.register(Customer, CustomerAdmin)

CodePudding user response:

you can make it property instead of method it will be

    @property
    def getFullName(self):
        return "%s %s" %(self.first_name, self.last_name)

then you can make custom filter

class FullNameFilter(SimpleListFilter):

   title = 'full name'
   parameter_name = 'full_name'

   def lookups(self, request, model_admin):
      return (
           ('True', True), 
           ('False', False)
             )

   def queryset(self, request, queryset): 
      if self.value():
          # If full_name=True filter is activated
          return queryset.filter(<Write your logic here>)
      else:
          # If full_name=True filter is activated
          return queryset.filter(<Write your other logic>)

CodePudding user response:

To be able to sort by a combined field, you have to adjust the queryset with annotations.

from django.contrib import admin
from django.db.models.functions import Concat

class CustomerAdmin(admin.ModelAdmin):
    list_display = [
        "pk",
        "first_name",
        "last_name",
        "full_name",
        "dob",
    ]

    def get_queryset(self, request):
        qs = self.model._default_manager.get_queryset()
        qs = qs.annotate(full_name=Concat('first_name', 'last_name'))
        ordering = self.get_ordering(request)
        if ordering:
            qs = qs.order_by(*ordering)
        return qs

    def full_name(self, obj):
        return obj.full_name

    full_name.admin_order_field = 'full_name'
    full_name.short_description = 'Full Name'
  • Related