To jest naprawdę podstawowy sposób na zrobienie tego. Zakładając, że ilość posiadanych danych nie jest zbyt duża, przyniesie to efekty. Możesz użyć tego w swoich widokach, zastępując funkcję get_queryset
i po prostu zwracając filtrowane. Możesz też użyć go jako metody statycznej na swojej klasie, jeśli planujesz używać jej wszędzie.
values = MyClass.objects.order_by('-created_ts').all()
filtered = []
existing = []
for value in values:
if value.my_integer not in existing:
existing.append(value.my_integer)
filtered.append(value)
Ponieważ lista jest uporządkowana według najnowszej wersji, zostaną one dodane do istniejącej pierwszej dla tej liczby całkowitej. Zrobiłem kilka podstawowych testów z tym, ale niewiele, więc może tam być wada lub dwa. Testowany z sqlite.
Edit
Tutaj jest znacznie szybsza wersja.
def iter_tools():
import itertools
qs = MyClass.objects.all()
filtered = []
group_by = itertools.groupby(qs, lambda x: x.my_integer)
for x in group_by:
filtered.append(sorted(x[1], key=lambda x: x.created_ts, reverse=True)[0])
return filtered
Zasadniczo sposób ten działa jest uzyskanie wszystkich obiektów z DB, grupując je przez liczbę całkowitą, a następnie sortowanie każdą grupę na podstawie znacznika czasu i coraz to pierwszy po jednym z każdej grupy. Przyspieszenie tego jeszcze bardziej wykracza poza moje umiejętności, ale jestem pewien, że jest kilka sposobów.
Oto timeit
tego jednego vs jednej wcześniejszej ze tylko jak 6 wpisów w dB:
In[]: timeit.timeit(manual, number=1500)
Out[]: 0.5577559471130371
In[]: timeit.timeit(iter_tools, number=1500)
Out[]: 0.39012885093688965
-----------------------------------------------
In[]: timeit.timeit(manual, number=5000)
Out[]: 1.770777940750122
In[]: timeit.timeit(iter_tools, number=5000)
Out[]: 1.2411231994628906
Edit 2: utworzonego 60000 obiektów do bazy danych, aby ją wypróbować niektóre dane. Wygenerowałem dane za pomocą django-fixtureless, więc liczby całkowite są całkowicie losowe, a znacznik czasu na nich wszystkich jest nowy datetime.now()
dla każdego obiektu.
In[]: timeit.timeit(manual, number=1)
Out[]: 11.946185827255249
In[]: timeit.timeit(iter_tools, number=1)
Out[]: 0.7811920642852783
In[]: timeit.timeit(iter_tools, number=100)
Out[]: 77.93837308883667
In[]: MyClass.objects.all().count()
Out[]: 60000
Uwaga na temat DB: W powyższych przykładach używałem sqlite3 tylko na moim komputerze lokalnym. Właśnie ustawiłem szybki mały serwer mysql jako vm i otrzymałem znacznie lepszy wynik prędkości.
In[16]: MyClass.objects.all().count()
Out[16]: 60000
In[17]: timeit.timeit(iter_tools, number=100)
Out[17]: 49.636733055114746
In[18]: timeit.timeit(iter_tools, number=1)
Out[18]: 0.4923059940338135
Tak czy inaczej, otrzymasz te same przedmioty, które zostały zwrócone.Jeśli wydajność jest problemem, zaleciłbym użycie itertools one lub niestandardowego zapytania sql.
"najnowsze" oznacza tylko jeden. – Gocht
"najnowsze created_ts dla każdej unikalnej wartości my_integer". To znaczy więcej niż jeden. –
@SaqibAli Twoje pytanie brzmi "Chciałbym pobrać instancje' MyClass' [...] ", ale zaakceptowałeś odpowiedź, która nie pobiera instancji' MyClass'. Zwraca słowniki. Nawet [skomentowałeś] (http://stackoverflow.com/questions/32359954/how-to-make-django-queryset-that-selects-records-w-max-value-winin-a-group#comment52598332_32361355) na innym odpowiedź, że chcesz instancji klasy. – Louis