2015-08-11 1 views
1

Я слил два querysets (qs1 и QS2), которые по отдельности работают нормально, следующим образом:Использование аннотата или добавочного поля для добавления в поле foreignkey к запросу? (Эквивалент SQL "AS"?)

qlist = [qs1, qs2] 
results = list(chain(qs1, qs2)) 

До сих пор, так хорошо - вышеуказанные работы. Но теперь я пытаюсь упорядочить результаты, используя следующие:

qlist = [qs1, qs2] 
results = sorted(chain(qs1, qs2), key=attrgetter('monthly_fee')) 

Проблема заключается в том, что второй QuerySet (QS2) относится к monthly_fee через ForeignKey; в то время как qs1 имеет доступность «month_fee». Вот QS2:

qs2 = Offer.objects.select_related('subscription') 
qs2 = qs2.order_by(subscription__monthly_fee) 

И упрощенные модели:

class Subscription(models.Model): 
    monthly_fee = models.IntegerField(null=False, blank=True, default=0) 
    name = models.CharField(max_length=120, null=True, blank=True) 

class Offer(models.Model): 
    promotion_name = models.CharField(max_length=120, null=True, blank=True) 
    subscription = models.ForeignKey(Subscription) 
    discount = models.IntegerField(null=False, blank=True, default=0) 

Я попытался с помощью .annotate() и .extra(), чтобы переименовать subscription__monthly_fee в Qs2 запроса следующим образом:

qs2 = Offer.objects.select_related('subscription').annotate(monthly_fee=subscription__monthly_fee) 

Но затем получить ошибку

global name 'subscription__monthly_fee' is not defined

Я нахожусь только в том, чтобы просто взломать это, переопределив методы .save() моих моделей, чтобы вручную добавлять month_fee к каждому экземпляру предложения всякий раз, когда создается объект. Но просто хотел проверить, нет ли лучшего способа?

Спасибо,

Майкл

ответ

0

Я использовал выражение F для достижения такого рода переименования ранее. Попробуйте следующее:

qs2 = Offer.objects.select_related('subscription').annotate(monthly_fee=F('subscription__monthly_fee')) 
+0

Thanks Mark. Раньше не использовались выражения F. Попробовал добавить это, но получил следующую ошибку: объект «F» не имеет атрибута «lookup» –

+0

Возможно, это было исправлено в Django 1.8. См. Документы: «Вы также можете использовать двойное обозначение подчеркивания для связи между объектами F()» (https://docs.djangoproject.com/en/1.8/topics/db/queries/#using-f-expressions -в-фильтры). – interDist

0

ОК, я нашел способ сделать это.

qs2 = Offer.objects.select_related('subscription').extra(select={'monthly_fee':'mobile_subscription.monthly_fee'}) 

где «мобильный» - это имя приложения Django. Я не понимал, что .extra DOES позволяет вам следить за внешними ключами, но вам действительно нужно указать фактическую таблицу базы данных и использовать нотацию SQL-точки.

Является ли приведенный выше фактический правильный способ, мы должны это делать? (т. е. удаление исходных имен/полей SQL-таблицы)

Я пытался использовать синтаксис Django, такой как .extra(select={'monthly_fee':'subscription__monthly_fee'}), который не работает!

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