6

我有两个模型:

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 回答