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'