I don't think you can do this purely with the ORM (at least, I couldn't find a way). However, there is a somewhat straightforward solution if you are willing to use extra() and some custom SQL.
Specifics may vary based on database, but this appears to work with sqlite3:
class WaiterAdmin(admin.ModelAdmin):
list_display = ('name', 'breakfast_avg', 'lunch_avg', 'dinner_avg')
def _avg_query(self, meal_type):
return """
SELECT AVG(service_rating) FROM {meal_table}
WHERE meal_type={meal_type} AND waiter_id={waiter_table}.id
""".format(meal_table=Meal._meta.db_table,
waiter_table=Waiter._meta.db_table,
meal_type=meal_type)
def queryset(self, request):
qs = super(WaiterAdmin, self).queryset(request)
qs = qs.extra({'breakfast_avg': self._avg_query(Meal.BREAKFAST),
'lunch_avg': self._avg_query(Meal.LUNCH),
'dinner_avg': self._avg_query(Meal.DINNER),
})
return qs
def breakfast_avg(self, obj):
return obj.breakfast_avg
breakfast_avg.short_description = 'Average Breakfast Rating'
breakfast_avg.admin_order_field = 'breakfast_avg'
def lunch_avg(self, obj):
return obj.lunch_avg
lunch_avg.short_description = 'Average Lunch Rating'
lunch_avg.admin_order_field = 'lunch_avg'
def dinner_avg(self, obj):
return obj.dinner_avg
dinner_avg.short_description = 'Average Dinner Rating'
dinner_avg.admin_order_field = 'dinner_avg'