Django: получить следующий и предыдущий идентификаторы элементов для определенного элемента с учетом нескольких параметров ИЛИ - PullRequest
1 голос
/ 09 сентября 2011

В моем приложении Django есть базовая модель предмета:

class Item(models.Model):
    name = models.CharField(max_length=200)
    brand = models.ForeignKey(User, related_name='items')
    price = models.CharField(max_length=10)
    upload_date = models.DateTimeField(auto_now=False, auto_now_add=True)

Для данного предмета я пытаюсь получить следующий и предыдущий предметы в БД.

Я знаю, что могу сделать это с помощью встроенного в Django Model.get_next_by_FOO(**kwargs), который прекрасно работает с полем upload_date, но мне нужно получить предыдущий и следующий элементы с определенными параметрами ИЛИ (например, элементы, имеющие определенной марки ИЛИ по определенной цене).

Я могу получить предыдущий элемент, используя такой запрос:

previous_item = Item.objects.filter(id__lt=item.id).filter(Q(brand__in=brands)|Q(price__lt=100))[:1]

Моя проблема со следующим пунктом. Выполнение того же запроса для следующего элемента приводит к самому последнему элементу в целом, который соответствует критериям, а не к элементу, который идет после текущего элемента в базе данных. Я понимаю, что это из-за того, как Django запрашивает базу данных, но не знаю, как обойти ее, чтобы получить элемент, который идет непосредственно после текущего элемента, который также соответствует критериям.

Существует ли быстрый и простой способ получить следующий элемент для определенного элемента с учетом нескольких параметров ИЛИ?

Спасибо!

1 Ответ

2 голосов
/ 09 сентября 2011

Я не проверял ничего из этого, поэтому мог просто говорить о моей заднице, но, может быть, это отправная точка?

Редактировать: О, да, вы достаточно ясно понимали проблему «ИЛИ», но я все же пропустил ее.Пробую еще раз.Основная идея состоит в том, чтобы преобразовать ваши запросы в списки и объединить списки.Но если подумать об этом сейчас - я думаю, что вы можете сами создавать реальные наборы запросов - разве это не может быть полезно в этом случае?Вы можете выполнить обычное тяжелое поднятие ИЛИ в функции, а затем передать обратно набор запросов, который может быть дополнительно обработан представлением.

def get_next(item, brand=None, max_price=None)
    """Returns the next item to the one provided"""

    # apply limits to brand/price as specified
    if brand is not None:
         brand_candy = Item.objects.filter(brand=brand)\
                              .values_list('id','update_date')
    if max_price is not None
         price_candy = Item.objects.filter(price__lt=max_price)\
                              .values_list('id','update_date')

    # arrange all candidates into a joined list
    # TODO: finish this to merge the lists and sort by update_date
    ids = brand_candy.join(price_candy)

    # find the location of the current item in the list 
    # TODO: handle not being there
    idx = ids.index(item.id)

    # TODO: handle edges of the list
    next_idx = idx + 1

    # pluck out the next item
    return Item.objects.get(id=ids[next_idx])
...