Ну, как вы его используете, так или иначе. Вы просто передаете менеджера в цикл for, а не в набор запросов, который можно было бы повторить. Однако photos
сам по себе является «связанным менеджером», а не фактической моделью ProductPhoto
, а связанные менеджеры основаны на первом указанном менеджере или objects
(менеджер по умолчанию).
Поскольку вы определяете live
, но также не определяет objects
, вы на самом деле не имеют objects
менеджер по этой модели, то есть это не получится: ProductPhoto.objects.all()
. Помните, что если вы определяете пользовательский менеджер на своей модели, Django больше не будет автоматически добавлять один из них: objects
.
Хорошая новость заключается в том, что, поскольку live
является менеджером по умолчанию в настоящее время, вы можете использовать его так же, как:
{% for photo in product.photos.all %}
И, вы получите только «живые» объекты. Плохая новость заключается в том, что это сломает много других вещей, которые зависят от менеджера по умолчанию, являющегося полным набором объектов (например, admin). Вы по существу скрываете блок «неживых» объектов.
То, что вы должны иметь это:
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()
objects
Обратите внимание, что определяется вручную и это первое, то есть он будет оставаться менеджером по умолчанию. Тем не менее, это больше не позволяет использовать ваш менеджер live
в шаблоне. В общем, что-то вроде этого, то лучше всего использовать один менеджер и добавить метод к нему вернуться «живые» объекты:
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)
Здесь мы фактически подклассов как QuerySet и Manager. Это позволит вам цепочки live
где угодно, а не только спереди. Например, если у вас был пользовательский менеджер без пользовательского запроса, вы могли бы сделать только ProductPhoto.objects.live().filter(...)
, а не ProductPhoto.objects.filter(...).live()
.
Таким образом, вы затем добавить, что в вашей модели, как objects
(занимает место по умолчанию один Django предоставляет):
class ProductPhoto(models.Model):
product = models.ForeignKey('Product', related_name='photos')
is_live = models.IntegerField(choices=LIVE_CHOICES, default=1)
objects = ProductPhotoManager()
И, наконец, вы будете иметь возможность использовать его в шаблоне:
{% for photo in product.photos.live %}
Благодарим Криса за лучший ответ и подробное объяснение. Я многому научился. – DavidL
Метод 'get_query_set' переименован в' get_queryset' в Django 1.6. – allcaps