Bene, il modo in cui lo si utilizza è sbagliato, comunque. Passeresti semplicemente il gestore nel ciclo for, non un queryset che potrebbe essere ripetuto. Tuttavia, photos
è esso stesso un "gestore correlato", non il modello effettivo ProductPhoto
e i relativi gestori sono basati sul primo gestore elencato o su objects
(il gestore predefinito).
Dal momento che, si definisce live
, ma non anche definire objects
, in realtà non si dispone di un objects
responsabile su questo modello, vale a dire il questo fallirà: ProductPhoto.objects.all()
. Ricorda, se definisci un gestore personalizzato sul tuo modello, Django non aggiungerà più automaticamente uno denominato objects
.
La buona notizia è che, poiché live
è il manager di default ora, è possibile utilizzarlo come:
{% for photo in product.photos.all %}
E, si otterrà solo gli oggetti "dal vivo". La cattiva notizia è che questo interromperà molte altre cose che dipendono dal gestore predefinito che è la raccolta completa di oggetti (ad esempio l'amministratore). Stai essenzialmente nascondendo il blocco di oggetti "non live".
Che cosa si dovrebbe avere è:
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()
noti che objects
è definito manualmente e è prima, il che significa che rimarrà il manager di default. Tuttavia, ciò non consente più di utilizzare il gestore live
nel modello. In generale, per qualcosa di simile, è meglio utilizzare solo un unico gestore e aggiungere un metodo ad esso per restituire gli oggetti "dal vivo":
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)
Qui, in realtà stiamo sottoclasse sia QuerySet e Manager. Ciò ti consentirà di mettere in catena live
ovunque anziché solo nella parte anteriore. Ad esempio, se hai appena avuto un gestore personalizzato senza un queryset personalizzato, potresti solo eseguire ProductPhoto.objects.live().filter(...)
e non ProductPhoto.objects.filter(...).live()
.
Così, poi si aggiunge che al vostro modello come objects
(prendendo il posto di quella di default Django fornisce):
class ProductPhoto(models.Model):
product = models.ForeignKey('Product', related_name='photos')
is_live = models.IntegerField(choices=LIVE_CHOICES, default=1)
objects = ProductPhotoManager()
E, infine, sarete in grado di usarlo nel modello:
{% for photo in product.photos.live %}
Grazie Chris per la migliore risposta e la spiegazione approfondita. Ho imparato molto. – DavidL
Il metodo 'get_query_set' viene rinominato in' get_queryset' in Django 1.6. – allcaps