Django: как использовать пользовательский менеджер в get_previous_by_FOO()?

У меня есть простая модель 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 }}

Проблема в том, что это возвращает предыдущий объект в наборе запросов по умолчанию (objects), а не в моем пользовательском (опубликовано).

Интересно, как я могу сообщить этим базовым функциям модели (get_previous_by_FOO) использовать мой пользовательский менеджер. Или, если это невозможно, как сделать то же самое с другим решением.

Спасибо заранее за любые советы.

Изменить

Представление вызывается таким образом в моем urlconf, используя object_detail из общих представлений.

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

Я использую Джанго 1.2.


person daks    schedule 17.01.2011    source источник
comment
Какой набор запросов вы используете в своих представлениях, где вы отображаете шаблоны, содержащие {{ object.get_previous }}? Может проблема кроется там   -  person Carles Barrobés    schedule 18.01.2011
comment
Я использую общие представления (django 1.2) с моим пользовательским менеджером. Он не использует этот.   -  person daks    schedule 18.01.2011
comment
Можете ли вы показать нам свой urlconf? Где вы ссылаетесь на представление   -  person Carles Barrobés    schedule 18.01.2011
comment
Из django.db.models: base.py get_next_or_previous_by_FIELD создает набор запросов из qs = self.__class_._default_manager...   -  person Carles Barrobés    schedule 18.01.2011


Ответы (1)


Фактически, функция Django get_next_or_previous_by_FIELD() (которая используется 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)

Это не очень чистое решение, так как мне нужно жестко закодировать набор запросов и используемое поле, но, по крайней мере, оно работает.

person daks    schedule 18.01.2011