6

私は2つのモデルを持っています:

class Product(models.Model):
    name = models.CharField(max_length=255)

class ProductPhoto(models.Model):
    product = models.ForeignKey('Product', related_name='photos')
    is_live = models.IntegerField(choices=LIVE_CHOICES, default=1)

    live = LiveManager()

class LiveManager(Manager):
    def get_query_set(self):
        return super(LiveManager, self).get_query_set().filter(is_live=1)

製品詳細テンプレートからライブ写真を取得しようとしています。

試した、

{% for photo in product.photos.live %}

これは機能せず、ドキュメントを見て、例が見つかりませんでした。テンプレートから外部キーのマネージャーを呼び出すことは可能ですか? 製品写真クエリセットを返す製品モデルで関数を作成する必要がありますか?

ありがとうございました。

4

1 に答える 1

26

とにかく使い方が間違っている。反復できるクエリセットではなく、マネージャーを 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)

ここでは、実際には QuerySetManager の両方をサブクラス化しています。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 %}
于 2012-05-21T18:27:30.977 に答える