2017-08-22 9 views
2

Ich habe dieses Modell:Django erhalten Zählung jedes Alter

class User_Data(AbstractUser): 
    date_of_birth  = models.DateField(null=True,blank=True) 
    city    = models.CharField(max_length=255,default='',null=True,blank=True) 
    address   = models.TextField(default='',null=True,blank=True) 
    gender    = models.TextField(default='',null=True,blank=True) 

Und ich brauche eine django Abfrage ausführen, um die Zählung jedes Alter zu erhalten. Etwas wie folgt aus:

Age || Count 
10 || 100 
11 || 50 
and so on..... 

Antwort

0

ist, was ich mit Lambda tat:

usersAge = map(lambda x: calculate_age(x[0]), User_Data.objects.values_list('date_of_birth')) 
    users_age_data_source = [[x, usersAge.count(x)] for x in set(usersAge)] 
    users_age_data_source = sorted(users_age_data_source, key=itemgetter(0)) 
0

Es gibt ein paar Möglichkeiten, dies zu tun. Ich musste in letzter Zeit etwas sehr ähnliches machen. Dieses Beispiel funktioniert in Postgres.

Hinweis: Ich habe den folgenden Code so geschrieben, wie ich es habe, so dass es syntaktisch funktioniert, und damit ich zwischen jedem Schritt schreiben kann. Aber Sie können diese zusammenketten, wenn Sie es wünschen.

Zuerst müssen wir das Abfrage-Set annotieren, um den Parameter 'age' zu erhalten. Da es als eine ganze Zahl nicht gespeichert ist, und sich täglich ändern können, können wir es ab dem Zeitpunkt der Geburt Feld berechnen, indem die ‚current_date‘ Funktion der Datenbank:

ud = User_Data.objects.annotate(
    age=RawSQL("""(DATE_PART('year', current_date) - DATE_PART('year', "app_userdata"."date_of_birth"))::integer""", []), 
) 

Hinweis: Sie werden die „app_userdata ändern müssen "Teil, der mit dem Tisch Ihres Modells übereinstimmt. Sie können dies aus dem _meta des Modells auswählen, aber das hängt nur davon ab, ob Sie das portabel machen wollen oder nicht. Verwenden Sie andernfalls eine Zeichenfolge .format(), um sie durch das _meta des Modells zu ersetzen. Wenn Ihnen das egal ist, geben Sie einfach den Tabellennamen ein.

Jetzt holen wir das ‚Alter‘ Wert, so dass wir eine ValuesQuerySet mit nur diesem Bereich

ud = ud.values('age') 

erhalten und dann diese queryset mit einer Zählung des Alters mit Anmerkungen versehen

ud = ud.annotate(
    count=Count('age'), 
) 

An diesem Punkt Wir haben ein ValuesQuerySet, das sowohl 'age' als auch 'count' als Felder hat. Bestellen Sie es, damit es auf eine vernünftige Weise herauskommt.

ud = ud.order_by('age') 

Und dort haben Sie es.

Sie müssen das Abfrage-Set in dieser Reihenfolge erstellen, sonst erhalten Sie einige interessante Ergebnisse. d. Sie können nicht alle Annotate zusammen gruppieren, da die zweite für die Zählung von der ersten abhängt, und da ein Kwargs-Diktat keine Vorstellung davon hat, in welcher Reihenfolge die Kwargs definiert wurden, wird die Abfrage bei der Feld-/Abhängigkeitsprüfung fehlschlagen .

Hoffe, das hilft.

Wenn Sie Postgres nicht verwenden, müssen Sie nur die RawSQL-Annotation ändern, um die von Ihnen verwendete Datenbank-Engine zu finden. Allerdings kann diese Engine das Jahr eines Datums erhalten, entweder von einem Feld oder von seiner eingebauten Funktion "aktuelles Datum". Wenn Sie dies als Integer abrufen können, funktioniert es genau so. Hier

+0

Danke für die Hilfe Ich habe etwas ähnliches mit Lambda 'usersAge = map (lambda x: calculate_age (x [0]), User_Data.objects .values_list ('date_of_birth')) users_age_data_source = [[x, usersAge.count (x)] für x im set (usersAge)] users_age_data_source = sortiert (users_age_data_source, key = itemgetter (0)) ' – Ahmedn1

Verwandte Themen