2015-06-15 3 views
2

я следующие модели (сокращёны для ясности):Джанго сортировать QuerySet по соответствующей модели поле

class Order(models.Model): 
    some fields 

class OrderStatus(models.Model): 
    order = models.ForiegnKey(Order) 
    status = models.CharField(choices=['ORDERED', 'IN_TRANSIT', 'RECEIVED']) 
    time = models.DateTimeField() 

Я хотел бы, чтобы отсортировать все заказы, которые содержат все три OrderStatuses от их порядка получением времени.

Другими словами, выберите заказы, которые имеют записи Заказал, в пути, и получил так:

Order.objects.filter(orderstatus__status=OrderStatus.ORDERED) 
      .filter(orderstatus__status=OrderStatus.IN_TRANSIT) 
      .filter(orderstatus__status=OrderStatus.RECEIVED) 

..., а затем отсортировать их по time области их соответствующей OrderStatus модели который status=OrderStatus.RECEIVED.

Здесь я застрял. Я прочитал Django docs в модификаторе запроса .extra() и прямой SQL-инъекции, но я все еще в недоумении. Могу ли я достичь этого с аннотированным полем и Q объектами, или мне лучше идти по маршруту .extra?

+0

Интересная проблема, и не знаю, как решить Это. Но мне интересно, какой дизайн. В вашей модели это выглядит так, как каждый заказ можно заказать, в пути и получить несколько раз. Это то, что вы намерены? Или существуют ограничения, которые не отображаются? (Вы упоминали, что это сокращенно для ясности.) Также может ли ПОЛУЧИТЬ ПОРЯДОК без предварительной регистрации и IN_TRANSIT? – Alain

+0

@ Хорошие наблюдения, но да, у нас есть ограничения переднего и заднего конца вокруг этого. Позволяет получить более полную информацию о данных и аналитике. Дело в том, что каждый заказ имеет только один статус. – grokpot

ответ

1

Вы не пытались сделать так?

На моих моделях он работал, как и ожидалось - order_by выбрал последний присоединился к OrderStatus так же, как вам нужно. Если вы не уверены, что вы можете проверить реальный запрос, как это (в Джанго оболочки):

from django.db import connection 
# perform query 
print(connection.queries) 

Также это можно сделать так:

OrderStatus.objects.filter(status=OrderStatus.RECEIVED) 
        .order_by('time').select_related('order') 
        .filter(order__orderstatus__status=OrderStatus.ORDERED) 
        .filter(order__orderstatus__status=OrderStatus.IN_TRANSIT) 
+0

Делает смысл. Благодаря! – grokpot

Смежные вопросы