Once a while a wild ticked occurred for one of the projects I was developing.
The issue was that they needed a rows with the totals and averages to be displayed at the end of the table in the admin changelist view for particular fields.
So here how it works
The issue was that they needed a rows with the totals and averages to be displayed at the end of the table in the admin changelist view for particular fields.
So here how it works
from django.contrib.admin.views.main import ChangeList from django.db.models import Sum, Avg from myapp.models import MyModelName class TotalAveragesChangeList(ChangeList): #provide the list of fields that we need to calculate averages and totals fields_to_total = ['amount', 'total_sum', 'paid_by_cash', 'paid_by_transfer',] def get_total_values(self, queryset): """ Get the totals """ #basically the total parameter is an empty instance of the given model total = MyModelName() total.custom_alias_name = "Totals" #the label for the totals row for field in self.fields_to_total: setattr(total, field, queryset.aggregate(Sum(field)).items()[0][1]) return total def get_average_values(self, queryset): """ Get the averages """ average = MyModelName() average.custom_alias_name = "Averages" #the label for the averages row for field in self.fields_to_total: setattr(average, field, queryset.aggregate(Avg(field)).items()[0][1]) return average def get_results(self, request): """ The model admin gets queryset results from this method and then displays it in the template """ super(TotalAveragesChangeList, self).get_results(request) #first get the totals from the current changelist total = self.get_total_values(self.query_set) #then get the averages average = self.get_average_values(self.query_set) #small hack. in order to get the objects loaded we need to call for #queryset results once so simple len function does it len(self.result_list) #and finally we add our custom rows to the resulting changelist self.result_list._result_cache.append(total) self.result_list._result_cache.append(average)
And all we need is just to set our custom changelist to the AdminModel
class MyModelNameAdmin(admin.ModelAdmin): def get_changelist(self, request, **kwargs): return TotalAveragesChangeList admin.site.register(MyModelName, MyModelNameAdmin)
Thanks a ton! I was looking for a way to figure this out
ReplyDeleteThanks AzMan, very usefull code. Could you post the code for?:
ReplyDelete- where you use custom_alias_name as label.
- where you set the CSS or clases for row background colors
Other question: The admin.py file is the correct place to define the TotalAveragesChangeList class?
Thanks a lot
You can place it there or take out into any outside module. I would place it into a different file, out of admin.
DeleteI have overriden built in admin css file using static files.
Hi Azamat,
ReplyDeleteMay I ask question?
Where does total.custom_alias_name = "Totals" #the label for the totals row come from?
I am getting the value correct but without label in the row.
Thnaks for your blog
Peter
Same question... the answer dont work for me...
DeleteYou need to add custom_alias_name property in your model.
ReplyDeleteFor example like this
def __unicode__(self):
if self.title:
return self.title
else:
return self.custom_alias_name
It has to be defined in your model class
So what happens here is that when it is an instance of model that is not loaded from db it will return the custom_alias_name instead of title
Cheers Azamat,
DeleteYou have given me hint,
Keep on writing more articles.
Peter
Thank you!
ReplyDeleteIn my case the subtotal is a calculated field (read_only). How to use in your method on the fields_to_total?
ReplyDelete#models.py
class DetVenda(models.Model):
quantity = models.IntegerField()
price = models.DecimalField(max_digits=8, decimal_places=2)
def _get_subtotal(self):
if self.quantity:
return self.price * self.quantity
subtotal = property(_get_subtotal)
#admin.py
class TotalChangeList(ChangeList):
fields_to_total = ['subtotal']
def get_total_values(self, queryset):
total = Sale()
total.custom_alias_name = "Totals"
for field in self.fields_to_total:
setattr(
total, field, queryset.aggregate(Sum(field)).items()[0][1])
return total
def get_results(self, request):
super(TotalChangeList, self).get_results(request)
total = self.get_total_values(self.query_set)
len(self.result_list)
self.result_list._result_cache.append(total)
FieldError at /admin/Sale:
Cannot resolve keyword 'total' into field. Choices are:
How to resolve this?
thank you
ReplyDeletehello
ReplyDeleteI'm very new to django.
What is self.query_set in your example
Perde modelleri
ReplyDeleteMobil onay
mobil ödeme bozdurma
Nft Nasil Alınır
ANKARA EVDEN EVE NAKLİYAT
trafik sigortası
Dedektör
kurma websitesi
aşk kitapları
SMM PANEL
ReplyDeleteSmm panel
iş ilanları
İNSTAGRAM TAKİPÇİ SATIN AL
hirdavatciburada.com
beyazesyateknikservisi.com.tr
servis
tiktok jeton hilesi
Good content. You write beautiful things.
ReplyDeletemrbahis
vbet
sportsbet
vbet
mrbahis
taksi
hacklink
sportsbet
korsan taksi
başakşehir
ReplyDeletebayrampaşa
beşiktaş
beykoz
beylikdüzü
QUİ