Django - 从django模板访问外键的Manager

时间:2012-05-21 17:33:46

标签: django django-models django-templates django-managers

我有两种模式:

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 %}

不起作用,查看文档,找不到示例。是否可以从模板中调用外键的管理器?我应该在产品模型中创建一个返回产品照片查询集的函数吗?

谢谢。

1 个答案:

答案 0 :(得分:24)

嗯,无论如何,你使用它的方式是错误的。您只需将管理器传递给for循环,而不是可以迭代的查询集。但是,photos本身就是一个“相关管理者”,而不是实际的ProductPhoto模型,相关管理器基于第一个列出的经理或objects(默认经理)。

既然你定义了live,但是也没有定义objects,那么你在这个模型上实际上没有objects经理,即这会失败:{{1 }}。请记住,如果您在模型上定义自定义管理器,Django将不再自动添加名为ProductPhoto.objects.all()的自定义管理器。

好消息是因为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

在这里,我们实际上是对QuerySet Manager进行子类化。这样您就可以将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) 链接到任何地方,而不仅仅是在前面。例如,如果您只有一个没有自定义查询集的自定义管理器,那么您将只能live而不能ProductPhoto.objects.live().filter(...)

因此,您将其作为ProductPhoto.objects.filter(...).live()添加到模型中(取代Django提供的默认值):

objects

最后,您将能够在模板中使用它:

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

    objects = ProductPhotoManager()