开发者

Django: how to use custom manager in get_previous_by_FOO()?

I have a simple model MyModel with a date field named publication_date. I also have a custom manager that filters my model based on this date field.

This custom manager is accessible by .published and the default one by .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(m开发者_运维百科odels.Model):
    ...
    publication_date = models.DateField(default=date.today())

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

This way, I got access to all objects in the admin but only to published ones in my views (using MyModel.published.all() queryset).

I also have

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

def get_next(self):
    return self.get_next_by_publication_date()

which I use in my templates: when viewing an object I can link to the previous and next object using

{{ object.get_previous }}

The problem is: this returns the previous object in the default queryset (objects) and not in my custom one (published).

I wonder how I can do to tell to this basic model functions (get_previous_by_FOO) to use my custom manager. Or, if it's not possible, how to do the same thing with another solution.

Thanks in advance for any advice.

Edit

The view is called this way in my urlconf, using object_detail from the generic views.

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

I'm using Django 1.2.


In fact, get_next_or_previous_by_FIELD() Django function (which is used by get_previous_by_publication_date...) uses the default_manager.

So I have adapted it to reimplement my own utility function

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)

This is not a very clean solution, as I need to hardcode the queryset and the field used, but at least it works.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜