2012-02-06 16 views
17

Mam modelu Data, związany z tabelą tak (model Data składa się z tylko IntegerField):Własne kolumny przy użyciu Django administratora

subject | year | quarter | sales | 
---------------------------------- 
    1 | 2010 | 1  | 20 | 
    1 | 2010 | 2  | 100 | 
    1 | 2010 | 3  | 100 | 
    1 | 2010 | 4  | 20 | 
    1 | 2011 | 1  | 30 | 
    1 | 2011 | 2  | 50 | 
    1 | 2011 | 4  | 40 | 
    2 | 2010 | 1  | 30 | 
    2 | 2010 | 2  | 20 | 
[..-GO ON this way...] 

chcę mieć stolik django-admin, w tylko do odczytu posiadające kolumny (current year = 2011, quarter = 1)

subject | sales current year | sales current quarter | sales last year | sales current quarter last year | 
---------------------------------------------------------------------------------------------------------- 
    1  | 110    | 30     | 240   | 20 
[AND SO ON] 

pytanie brzmi: jest możliwe zrobić przy użyciu django-admin? Jakie jest wyjście?

Odpowiedz

28

Można użyć metod na swojej Model lub swojej ModelAdmin jako elementów dla list_display. Zobacz: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display

Ponieważ są to metody, które mogą być przydatne poza adminem, proponuję dodać je do twojego Model.

from django.db.models import Sum 

class Data(models.Model): 
    ... 

    # Method used by `get_current_year_sales` and `get_last_year_sales` 
    # to stay DRY. Not for use directly in admin. 
    def get_year_sales(self, year): 
     qs = self.model._default_manager.filter(year=year) 
     sales_agg = qs.aggregate(Sum('sales')) 
     return sales_agg['sales__sum'] 

    # Method used by `get_current_quarter_sales` and `get_last_quarter_sales` 
    # to stay DRY. Not for use directly in admin. 
    def get_quarter_sales(self, year, quarter): 
     qs = self.model._default_manager.filter(year=year, quarter=quarter) 
     sales_agg = qs.aggregate(Sum('sales')) 
     return sales_agg['sales__sum'] 

    def get_current_year_sales(self): 
     return self.get_year_sales(datetime.now().year) 
    get_current_year_sales.short_description = 'Sales (Current Year)' 

    def get_last_year_sales(self): 
     return self.get_year_sales(datetime.now().year-1) 
    get_last_year_sales.short_description = 'Sales (Last Year)' 

    def get_current_quarter_sales(self): 
     # Determine current quarter logic here as `current_quarter` 
     # `quarter_year` will likely be same as current year here, 
     # but will need to be calculated for previous quarter 
     return self.get_quarter_sales(quarter_year, current_quarter) 
    get_current_quarter_sales.short_description = 'Sales (Current Quarter)' 

    def get_current_quarter_sales(self): 
     # Logic here to determine last quarter as `last_quarter` 
     # Logic to determine what year last quarter was in as `quarter_year` 
     return self.get_quarter_sales(quarter_year, last_quarter) 
    get_last_quarter_sales.short_description = 'Sales (Last Quarter)' 

short_description atrybut określa co admin pokaże jak nagłówka wiersz dla tych metod. Tak więc, skoro masz to wszystko na swoim miejscu, trzeba tylko zmodyfikować twoje ModelAdmin „s list_display atrybut stylu:

class DataAdmin(admin.ModelAdmin): 
    ... 
    list_display = ('subject', 'get_current_year_sales', 'get_last_year_sales', 'get_current_quarter_sales', 'get_last_quarter_sales') 
+0

Ostatnie pytanie, jeśli chcę, aby posortować kolumnę to nie działa, ponieważ są to metody, a nie atrybuty , prawdziwe? Dziękuję Ci! – zambotn

+1

Sprawdź [to] (http://stackoverflow.com/questions/2168475/django-admin-how-to-sort-by-of-the-custom-list-display-fields-that-has-no -d) i [this] (http://stackoverflow.com/questions/2647632/how-to-allow-sorting-in-the-django-admin-by-a-custom-list-display-field-which-whi- d) –

+0

Prawda. Możesz dodać możliwość sortowania, informując django, które pole ma być używane z ' .admin_order_field = 'my_field'', ale w tym scenariuszu nie ma dobrego pola do powiązania z tym polem. –

6

Coś jak to powinno działać (niesprawdzone):

# models.py 
class Data(models.Model): 
    year = models.DateField() 
    sales = models.IntegerField() 
    # ... 

    def sales_current_year(self): 
     return self.model._default_manager.get_queryset().filter(year=2012).annotate(Sum('sales')) 

# admin.py 
class DataAdmin(admin.ModelAdmin): 
     list_display = ('sales_current_year',) 
Powiązane problemy