Hay,我正在使用django 1.2,我想知道如何计算原始查询集(RawQuerySet)中的行。
传统的.count()方法不起作用。
继承我的查询
query = "SELECT *, ((ACOS(SIN(%s * PI() / 180) * SIN(lat * PI() / 180) + COS(%s * PI() / 180) * COS(lat * PI() / 180) * COS((%s - lon) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) AS distance FROM app_car WHERE price BETWEEN %s AND %s HAVING distance<=%s ORDER BY distance ASC"
cars = Car.objects.raw(query, [lat, lat, lon, min_price, max_price, miles])
return HttpResponse( cars )
它的回归
Car_Deferred_model_id_user_id object
有什么想法吗?
答案 0 :(得分:26)
使用'len()'函数。这会给:
query = "SELECT *, ((ACOS(SIN(%s * PI() / 180) * SIN(lat * PI() / 180) + COS(%s * PI() / 180) * COS(lat * PI() / 180) * COS((%s - lon) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) AS distance FROM app_car WHERE price BETWEEN %s AND %s HAVING distance<=%s ORDER BY distance ASC"
cars = Car.objects.raw(query, [lat, lat, lon, min_price, max_price, miles])
return HttpResponse(len(list(cars))
除此之外:有关Django 1.2 Model.objects.raw()方法的一些有用信息:http://djangoadvent.com/1.2/smoothing-curve/ [看起来该网站可能已过期,但互联网档案馆有:http://web.archive.org/web/20110513122309/http://djangoadvent.com/1.2/smoothing-curve/ ]
答案 1 :(得分:7)
说实话,如果您想要的只是RawQuerySet中的记录总数,那么无论如何都应该避免将RawQuerySet强制转换为列表。
将RawQuerySet转换为列表将遍历与查询匹配的每个记录。这对服务器来说可能很麻烦。请改用count()。这可以通过将计数()包装在用于生成RawQuerySet的原始SQL周围来实现。
我用它来解决问题:
def add_len_protocol_to_raw_sql_query( query ):
"""
Adds/Overrides a dynamic implementation of the length protocol to the definition of RawQuerySet for the remainder of this thread's lifespan
"""
from django.db.models.query import RawQuerySet
def __len__( self ):
from django.db import connection
sql = 'SELECT COUNT(*) FROM (' + query + ') B;'
cursor = connection.cursor()
cursor.execute( sql )
row = cursor.fetchone()
return row[ 0 ]
setattr( RawQuerySet, '__len__', __len__ )
query = 'SELECT * FROM A_TABLE_OF_MINE'
add_len_protocol_to_raw_sql_query( query )
这对RawQuerySet进行了动态修改,以便它响应len()协议。
这在性能方面要好得多,你可能存在一个缺点:如果你不止一次使用RawQuerySet,那么最好放弃动态 _ len _ 实施。
你们是否知道 _ len _ 方法是否会被调用者的执行上下文约束?如果在Apache上使用MOD_WSGI,这是否意味着调用者进程中的所有线程将共享修改后的定义?
答案 2 :(得分:4)
以下是基于user871977的改进解决方案:
from django.db import connection
def get_len(rawqueryset):
def __len__(self):
params = ["""'%s'""" % p for p in self.params]
sql = 'SELECT COUNT(*) FROM (' + (rawqueryset.raw_query % tuple(params)) + ') B;'
cursor = connection.cursor()
cursor.execute(sql)
row = cursor.fetchone()
return row[0]
return __len__
rawqueryset = .... # a RawQuerySet instance
setattr(type(rawqueryset), '__len__', get_len(rawqueryset))
答案 3 :(得分:2)
没有'count'的原因是因为您需要对数据库进行额外的“count(*)”查询以了解结果集的大小。
请记住,调用list(cars)
会将所有结果加载到内存中。这允许您使用len
获取计数,但如果您有大的结果集,则可能是一项昂贵的操作。