使用annotate或extra将foreignkey的字段添加到queryset? (相当于SQL“AS”?)

时间:2015-08-11 04:28:55

标签: python django django-queryset django-orm

我合并了两个查询集(qs1和qs2),它们分别正常工作,如下所示:

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

到目前为止,这么好 - 以上的作品。但现在我正在尝试使用以下内容来排序结果:

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

问题是第二个查询集(qs2)通过ForeignKey引用monthly_fee;而qs1有'monthly_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()重命名查询qs2中的subscription__monthly_fee,如下所示:

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

然后得到错误

  

全局名称'subscription__monthly_fee'未定义

我只是通过覆盖我的模型的.save()方法来手动将every_fee手动添加到每个Offer实例,只要创建了一个对象。但只是想检查是否有更好的方法?

谢谢,

迈克尔

2 个答案:

答案 0 :(得分:1)

我之前使用过F表达式来实现这种重命名。试试这个:

@implementation NSView (Vibrancy)


- (instancetype) insertVibrancyView
{
    Class vibrantClass = NSClassFromString( @"NSVisualEffectView" );
    if( vibrantClass ) {
        NSVisualEffectView* vibrant = [[vibrantClass alloc] initWithFrame:self.bounds];
        [vibrant setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];

        NSArray* mySubviews = [self.subviews copy];
        for( NSView* aView in mySubviews ) {
            [aView removeFromSuperview];
            [vibrant addSubview:aView];
        }

        [self addSubview:vibrant];

        return vibrant;
    }

    return nil;
}

@end

答案 1 :(得分:1)

好的,我找到了办法。

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

移动'是Django应用程序的名称。我没有意识到.extra允许你遵循外键,但实际上你必须指定实际的数据库表并使用SQL点表示法。

以上是我们应该做的实际正确方法吗? (即删除原始SQL表名/字段)

我一直在尝试使用诸如.extra(select={'monthly_fee':'subscription__monthly_fee'})之类的Django语法,但这些语法并不起作用!