Django:如何在get_previous_by_FOO()中使用自定义管理器?

时间:2011-01-17 21:32:00

标签: django django-models django-queryset

我有一个简单的模型 MyModel ,其日期字段名为 publication_date 。我还有一个自定义管理器,可根据此日期字段过滤我的模型。

此自定义管理器可通过 .published 访问,默认可通过 .objects 访问。

from datetime import date, datetime
from django.db import models

class MyModelManager(models.Manager):
    def get_query_set(self):
        q = super(MyModelManager, self).get_query_set()
        return q.filter(publication_date__lte=datetime.now()) 

class MyModel(models.Model):
    ...
    publication_date = models.DateField(default=date.today())

    objects = models.Manager()
    published = MyModelManager()

这样,我可以访问管理员中的所有对象,但只能访问我的视图中的已发布对象(使用 MyModel.published.all()查询集)。

我也有

def get_previous(self):
    return self.get_previous_by_publication_date()

def get_next(self):
    return self.get_next_by_publication_date()
我在模板中使用的

:查看对象时,我可以使用

链接到上一个和下一个对象
{{ object.get_previous }}

问题是:这会返回默认查询集中的上一个对象(对象),而不是我的自定义对象(已发布)。

我想知道如何告诉这个基本模型函数(get_previous_by_FOO)来使用我的自定义管理器。 或者,如果不可能,如何用另一种解决方案做同样的事情。

提前感谢任何建议。

修改

在我的urlconf中使用通用视图中的object_detail以这种方式调用视图。

(r'^(?P<slug>[\w-]+)$', object_detail,
    {
     'queryset': MyModel.published.all(),
     'slug_field': 'slug',
    },
    'mymodel-detail'
),

我正在使用Django 1.2。

1 个答案:

答案 0 :(得分:1)

实际上,get_next_or_previous_by_FIELD()Django函数(由get_previous_by_publication_date ...使用)使用default_manager。

所以我已经调整它以重新实现我自己的效用函数

def _own_get_next_or_previous_by_FIELD(self, field, is_next):
    if not self.pk:
        raise ValueError("get_next/get_previous cannot be used on unsaved objects.")
    op = is_next and 'gt' or 'lt'
    order = not is_next and '-' or ''
    param = smart_str(getattr(self, field.attname))
    q = Q(**{'%s__%s' % (field.name, op): param})
    q = q|Q(**{field.name: param, 'pk__%s' % op: self.pk})
    qs = MyModel.published.filter(q).order_by('%s%s' % (order, field.name), '%spk' % order)
    try:
        return qs[0]
    except IndexError:

def get_previous(self):
    return self._own_get_next_or_previous_by_FIELD(MyModel._meta.fields[4], False)

def get_next(self):
    return self._own_get_next_or_previous_by_FIELD(MyModel._meta.fields[4], True)

这不是一个非常干净的解决方案,因为我需要对查询集和使用的字段进行硬编码,但至少它是有效的。