我目前正在尝试基于三种模型返回查询集。
位置模型
class Location(models.Model):
...
lat = models.FloatField()
lng = models.FloatField()
用户模型(从Django用户扩展)
class UserProfile(models.Model):
...
user = OneToOneField(User)
locations = ManyToManyField(Location)
案例模型
class Case(models.Model):
...
owner = models.ForeignKey(User)
completed = models.BooleanField()
我正在使用geopy
返回接近输入经纬度的位置
def get_locations_nearby_coords(latitude, longitude, max_distance=None):
"""
Return objects sorted by distance to specified coordinates
which distance is less than max_distance given in kilometers
"""
# Great circle distance formula
gcd_formula = "6371 * acos(cos(radians(%s)) * cos(radians(lat)) * cos(radians(long) - radians(%s)) + sin(radians(%s)) * sin(radians(lat)))"
distance_raw_sql = RawSQL(
gcd_formula,
(latitude, longitude, latitude)
)
qs = Location.objects.all().annotate(
distance=distance_raw_sql).order_by('distance')
if max_distance is not None:
qs = qs.filter(distance__lt=max_distance)
return qs
我要返回的是按每个locations
完成的案例数排序的最接近的UserProfile
十位
一个用户可以有多个位置,并且一个位置可以与许多用户相关联,因此我为什么要使用m2m字段。
我没有任何重复项,但是,如果某个位置有多个用户,则该位置可以在列表中显示两次,但是最终列表应切成10。
编辑:
试图弄清楚应该返回什么。
假设我有3个位置靠近我(这是已知数据)
1. Location 1 (Closest)
2. Location 2
3. Location 3 (Furthest)
Location 1
有1个用户,已完成3个案例。 Location 2
有两个用户,用户1已完成10个案例,用户2已完成2个。Location 3
拥有1个用户,具有4个完整案例。应该返回的内容如下
1. Location 2 - User 1 - 10 Cases
2. Location 3 - User 1 - 4 Cases
3. Location 1 - User 1 - 3 Cases
4. Location 2 - User 2 - 2 Cases
答案 0 :(得分:1)
首先,我建议应用显式关系名称以在查询中使用它们。
要将完整的病例数附加到查询集,您可以使用以下方法:
qs = qs.annotate(completed_cases=Count('user__case', filter=Q(user__case__completed=True))
最后的切片与[:10]
qs = qs.order_by('distance', '-completed_cases`, 'id', )[:10]
id-为避免相同距离和案例数的随机性。
# finding locations
...
qs = qs.order_by('distance', 'id', )[:10]
# finding users with completed cases
final_qs = User.objects.filter(locations__in=qs, ).\
annotate(
completed_cases=Count('case', filter=Q(case__completed=True),
location_id=F('locations__id'),
).order_by('-completed_cases', 'id')[:10]