django中的内部函数以合理的方式向查询集添加新表是什么?

时间:2010-08-25 09:07:16

标签: django django-queryset

在django 1.2中:

我有一个带有额外参数的查询集,该参数引用了一个表,该表当前未包含在django为此查询集生成的查询中。

如果我将order_by添加到引用另一个表的queryset,则django以正确的方式将连接添加到另一个表,并且额外的工作。但是没有order_by,额外的参数就会失败。我可以在另一个表中添加一个无用的二级order_by,但我认为应该有更好的方法来实现它。

以合理的方式添加联接的django函数是什么?我知道这必须在某个地方被召唤。

以下是一些示例代码。它选择给定用户的所有读数,并使用存储在“朋友”中的另一个用户给出的评级(如果有)来注释结果。

class Book(models.Model):
    name = models.CharField(max_length=200)
    urlname = models.CharField(max_length=200)
    entrydate=models.DateTimeField(auto_now_add=True)

class Reading(models.Model):
    book=models.ForeignKey(Book,related_name='readings')
    user=models.ForeignKey(User)
    rating=models.IntegerField()
    entrydate=models.DateTimeField(auto_now_add=True)

readings=Reading.objects.filter(user=user).order_by('entrydate')

friendrating='(select rating from proj_reading where user_id=%d and \
book_id=proj_book.id and rating in (1,2,3,4,5,6))'%friend.id

readings=readings.extra(select={'friendrating':friendrating})

目前,读数无法正常工作,因为未正确设置读数连接。但是,如果我通过以下方式添加订单:

.order_by('entrydate','reading__entrydate')

django神奇地知道通过外键添加内部联接,我得到了我想要的东西。

其他信息:

print readings.query ==>

select ((select rating from proj_reading where user_id=2 and book_id=proj_book.id and  rating in (1,2,3,4,5,6)) as 'hisrating', proj_reading.id, proj_reading.user_id, proj_reading.rating, proj_reading.entrydate from proj_reading where proj_reading.user_id=1;

假设 user.id = 1 friend.id = 2

错误是:

OperationalError: Unknown column proj_book.id in 'where clause'

并且它发生是因为表proj_book未包含在查询中。重申我上面所说的 - 如果我现在读readings2 = readings.order_by('book__entrydate')我可以看到正确的连接已设置并且查询有效。

理想情况下,我只想弄清楚qs.query函数的名称是什么,它会查看两个表,并确定它们是如何通过外键连接的,只需手动调用即可。

2 个答案:

答案 0 :(得分:1)

您生成的查询:

选择((从proj_reading中选择等级,其中user_id = 2,book_id = proj_book .id并在(1,2,3,4,5,6)中评级为'hisrating',proj_reading来自proj_reading的.id,proj_reading.user_id,proj_reading.rating,proj_reading.entrydate,其中proj_reading.user_id = 1;

  1. db无法理解proj_book的含义,因为它不包含在(来自表或内连接)中。

  2. 当你添加order_by时,你得到了预期的结果,因为order_by查询是在proj_book和proj_reading之间添加内连接。

  3. 据我了解,如果您推荐Book中的任何其他专栏,而不仅仅是order_by,您将得到类似的结果。

    • Q1 = Reading.objects.filter(user = user)。 exclude(Book__name ='')#排除要添加JOIN的力量
    • Q2 =“从proj_reading中选择评级,其中user_id =%d”%user.id
    • 结果= Q1.extra(“foo”:Q2)

    这样,在步骤Q1,您强制DJango在Book表上添加连接,这不是默认值,除非您访问Book表的任何字段。

答案 1 :(得分:0)

你的意思是:

class SomeModel(models.Model)
    id = models.IntegerField()
    ...


class SomeOtherModel(models.Model)
    otherfield = models.ForeignKey(SomeModel)

qrst = SomeOtherModel.objects.filter(otherfield__id=1)

您可以使用“__”创建表连接。

编辑: 它不会工作,因为你没有正确定义表连接。

myrating='(select rating from proj_reading inner join proj_book on (proj_book.id=proj_reading_id) where proj_reading.user_id=%d and rating in (1,2,3,4,5,6))'%user.id)'

这是一个pesdocode,未经过测试。

但是,我建议你使用django过滤器而不是编写SQL查询。

read = Reading.objects.filter(book__urlname__icontains="smith", user_id=user.id, rating__in=(1,2,3,4,5,6)).values('rating')

Documentation了解详情。