とにかく使い方が間違っている。反復できるクエリセットではなく、マネージャーを for ループに渡すだけです。ただし、photos
それ自体は「関連マネージャー」であり、実際のProductPhoto
モデルではなく、関連マネージャーは最初にリストされたマネージャーまたはobjects
(デフォルト マネージャー) に基づいています。
を定義live
しているが も定義しobjects
ていないため、実際にはobjects
このモデルにマネージャーがありません。つまり、 this は失敗します: ProductPhoto.objects.all()
。モデルにカスタム マネージャーを定義すると、Django は という名前のマネージャーを自動的に追加しなくなりますobjects
。
良いニュースは、live
現在デフォルトのマネージャーであるため、次のように使用できることです。
{% for photo in product.photos.all %}
そして、「ライブ」オブジェクトのみを取得します。悪いニュースは、デフォルトのマネージャーがオブジェクトの完全なコレクション (管理者など) であることに依存する他の多くのことを壊してしまうことです。基本的に、「非ライブ」オブジェクトのブロックを隠しています。
あなたが持っているべきものは次のとおりです。
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 %}