2009-08-31 12 views
5

Powiedzmy mam dwa modele wyglądające tak:Jak pobrać dwa najlepsze produkty dla każdego rodzaju produktu?

 
class ProductType(models.Model): 
    product_type = models.CharField(max_length=100) 

class Product(models.Model): 
    name = models.CharField(max_length=200) 
    slug = models.SlugField() 

    product_type = models.ForeignKey(ProductType) 

    score = models.PositiveIntegerField(default=0) 

Teraz chcę, aby pobrać dwie najlepsze produkty (dwóch z najwyższym wynikiem) z każdego Producttype. Więc jeśli mam Telefony, komputery, telewizory jako ProductTypes Chcę dwa najlepsze telefony, komputery, telewizory.

Ponieważ nawet nie wiem, jak to zrobić w MySQL, próbowałem szukać rozwiązania MySQL, ale te, które uważam, są niezwykle złożone i nie wydaje mi się to zbyt skomplikowane.

Jestem skłonny do tworzenia własnego modelu dla najlepszych produktów i mam cronjob to naprawić, ale chciałbym zobaczyć, czy jest łatwiejsze rozwiązanie tego.

Odpowiedz

4

Cóż, można zrobić metoda wewnątrz klasy Producttype zwracającej dwa najlepsze wyniki dla swoich produktów:

class ProductType(models.Model): 
    product_type = models.CharField(max_length=100) 

    def TopTwoProducts(self): 
     return self.product_set.order_by('-score')[0:2] 

Wtedy po prostu zrobić coś takiego:

for type in ProductType.objects.all(): 
    type.TopTwoProducts() 
+0

Inteligentne rozwiązanie, podoba mi się! Dzięki. – rinti

+0

Nie rozumiem ... dlaczego używasz pętli? – IProblemFactory

+1

Używasz pętli for tylko wtedy, gdy przychodzi czas na dostęp do dwóch najlepszych produktów (takich jak umieszczenie ich w szablonie lub cokolwiek innego). – Adam

4

natomiast Adama rozwiązanie jest poprawne, bardziej django-asem byłoby użycie menedżera.

See Managers versus class methods na blogu James Bennetta

Wśród innych zalet:

  • menedżer wykonuje cały kod zapytania specyficzne, unikając zaśmiecać klasie modelu
  • tej samej klasy menedżer mogą być udostępniane spośród kilku klas
  • menedżera można używać bezpośrednio w klasie modelu lub za pomocą relacji jeden do wielu lub m2m

Tak na powyższe pytanie:

from django.db import models 
from django.db.models.manager import Manager 

class ProductScoreManager(Manager): 

    use_for_related_field = True 

    def top_score(self, limit=2): 
     return self.get_query_set().order_by('-score')[:limit] 

Następnie dodać tej klasy menedżera jako domyślnego menedżera o produkt:

class Product(models.Model): 
    ... 
    objects = ProductScoreManager() 
    ... 

Teraz, dzięki obiektów nadpisanie domyślnego menedżera, a use_for_related_field umożliwiając jego użycie w zapytaniach dotyczących relacji, metoda top_score może być używana w każdym modelu związanym z produktami.

myproducttype = ProductType.objects.get(...) 
myproducttype.products.top_score() # return top 2 products 

Pozwala to na bardziej spójną składnię: odnośne produkty są zawsze dostępne poprzez produktów, top_score działające jako filtr. Ponadto klasa ProductType nie jest już bardziej zagmatwana w logice zapytań produktu.

+0

Dzięki, zagłębię się w to jutro! – rinti

Powiązane problemy