Tak czy inaczej, sposób w jaki go używasz jest zły. Po prostu przekazujesz menedżera do pętli for, a nie zapytanie, które może być iterowane. Jednakże, photos
sam jest "powiązanym menedżerem", a nie rzeczywistym modelem ProductPhoto
, a powiązani menedżerowie są oparci na pierwszym wymienionym menedżerze lub objects
(domyślny menedżer).
Ponieważ zdefiniować live
, ale nie również zdefiniować objects
, w rzeczywistości nie mają menedżera objects
na tym modelu, to znaczy to nie powiedzie: ProductPhoto.objects.all()
. Pamiętaj, że jeśli zdefiniujesz niestandardowego menedżera w swoim modelu, Django nie będzie już automatycznie dodawać jednego o nazwie objects
.
Dobrą wiadomością jest to, że ponieważ live
to domyślny menedżer teraz, można go używać jak:
{% for photo in product.photos.all %}
I, dostaniesz tylko obiekty „na żywo”. Zła wiadomość jest taka, że złamie to wiele innych rzeczy, które zależą od domyślnego menedżera będącego pełną kolekcją obiektów (na przykład admin). W zasadzie ukrywasz blok obiektów "nieżywych".
Co trzeba mieć to:
class ProductPhoto(models.Model):
product = models.ForeignKey('Product', related_name='photos')
is_live = models.IntegerField(choices=LIVE_CHOICES, default=1)
objects = models.Manager()
live = LiveManager()
Uwaga, objects
jest definiowana ręcznie i to pierwsze, co oznacza, że pozostanie domyślny menedżer. Jednak to nie pozwala już na użycie menedżera live
w szablonie. Ogólnie rzecz biorąc, na coś takiego, to najlepiej po prostu użyć jednego menedżera i dodać metodę do niego wrócić obiektów „na żywo”:
class ProductPhotoQuerySet(models.query.QuerySet):
def live(self):
return self.filter(is_live=1)
class ProductPhotoManager(models.Manager):
use_for_related_fields = True
def get_query_set(self):
return ProductPhotoQuerySet(self.model)
def live(self, *args, **kwargs):
return self.get_query_set().live(*args, **kwargs)
Tutaj jesteśmy rzeczywiście instacji zarówno QuerySet i Manager. Umożliwi to podłączenie się do dowolnego miejsca, a nie tylko z przodu. Na przykład, gdybyś miał niestandardowego menedżera bez niestandardowego zestawu zapytań, mógłbyś wykonywać tylko ProductPhoto.objects.live().filter(...)
, a nie ProductPhoto.objects.filter(...).live()
.
Więc, następnie dodać, że do modelu jako objects
(zajmując miejsce domyślnego jeden Django dostarcza):
class ProductPhoto(models.Model):
product = models.ForeignKey('Product', related_name='photos')
is_live = models.IntegerField(choices=LIVE_CHOICES, default=1)
objects = ProductPhotoManager()
I wreszcie będziesz mógł używać go w szablonie:
{% for photo in product.photos.live %}
Dziękuję Chris za najlepszą odpowiedź i dokładne wyjaśnienie. Dużo się nauczyłem. – DavidL
Metoda 'get_query_set' zostaje zmieniona na' get_queryset' w Django 1.6. – allcaps