2010-05-28 1 views
4

Можно создать дубликат:
django - ordering queryset by a calculated fieldДжанго QuerySet упорядоченность выражением

Как я могу использовать order_by как order_by ('FIELD1' * 'field2') Например у меня есть элементы с ценой перечисленные в разных валютах, поэтому для заказа предметов - я должен сделать конвертацию валюты.

class Currency(models.Model): 
    code = models.CharField(max_length=3, primary_key=True) 
    rateToUSD = models.DecimalField(max_digits=20,decimal_places=10) 

class Item(models.Model): 
    priceRT  = models.DecimalField(max_digits=15, decimal_places=2, default=0) 
    cur  = models.ForeignKey(Currency) 

Я хотел бы иметь что-то вроде:

Item.objects.all().order_by(F('priceRT')*F('cur__rateToUSD')) 

Но, к сожалению, он не работает, я также faild с аннотирования. Как можно упорядочить заказ QuerySet по результату умножения полей 2 модели.

ответ

4

Используйте метод extra(). В частности, аргумент select для указания уравнения и аргумент order_by для выполнения заказа.

+1

Спасибо! В моем случае решение выглядит так: Item.objects.filter (q & qDates) .extra (выберите = {'usdPrice': 'SELECT airsale_item.priceRT/toUSD FROM airsale_currency WHERE airsale_currency.code = airsale_item.cur_id'}). Order_by ('usdPrice') К сожалению, я не смог использовать результат одного дополнительного в следующем. как I.objects.extra ({'xx': ....}). Extra ({'yy': 'xx' * 2}) django (db на самом деле) поле throw xx отсутствует. В любом случае, моя проблема решена, спасибо – Andrew

2

Сверляющий путь: добавьте дополнительное поле в класс Item под названием priceUSD и заполните его с помощью метода экономии при переопределении. означает, что у вас нет нагрузки на выполнение вычислений на каждый запрос - только на каждое обновление. так ли это хорошо или нет, будет зависеть от, как правило, является ли вы писать более или читать больше (учитывая ваш вопрос, может быть, это читать?)

что-то вроде этого:

class Item(models.Model): 
    priceRT  = models.DecimalField(max_digits=15, decimal_places=2, default=0) 
    cur  = models.ForeignKey(Currency) 
    priceUSD = models.DecimalField(max_digits=15, decimal_places=2, default=0) 

    def save(self,*args,**kwargs) 
     self.priceUSD = self.priceRT * self.cur.rateToUSD 
     super(Model,self).save(*args,**kwargs) 

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

+0

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