7

我有名为“has_location”和“位置”的表。'has_location' 有user_haslocation_id它自己的id,由 django 本身给出。

“位置”有更多列。

现在我想获取某个特定用户的所有位置。我所做的是..(user.id 是已知的):

users_locations_id = has_location.objects.filter(user_has__exact=user.id)
locations = Location.objects.filter(id__in=users_locations_id)
print len(locations)

但我得到0了这个print。我在数据库中有数据。__in但是我有一种不接受模型ID的感觉,是吗?

谢谢

4

3 回答 3

11

在 Django 中使用__in这种查询是一种常见的反模式:由于它的简单性,它很诱人,但它在大多数数据库中的扩展性都很差。请参阅Christophe Pettus 的演示文稿中的幻灯片 66ff 。

用户和位置之间存在多对多关系,由has_location表表示。您通常会使用ManyToManyField带有through表的 a 向 Django 描述这一点,如下所示:

class Location(models.Model):
    # ...

class User(models.Model):
    locations = models.ManyToManyField(Location, through = 'LocationUser')
    # ...

class LocationUser(models.Model):
    location = models.ForeignKey(Location)
    user = models.ForeignKey(User)
    class Meta:
         db_table = 'has_location'

然后您可以像这样获取用户的位置:

user.locations.all()

您可以在过滤器操作中查询位置:

User.objects.filter(locations__name = 'Barcelona')

prefetch_related()并且您可以使用查询集上的方法请求有效地获取用户的相关位置。

于 2013-03-26T12:14:44.003 回答
7

您正在使用 has_location 自己的 id 来过滤位置。您必须使用location_ids 来过滤位置:

user_haslocations = has_location.objects.filter(user_has=user)
locations = Location.objects.filter(id__in=user_haslocations.values('location_id'))

您还可以通过反向关系直接过滤位置:

location = Location.objects.filter(has_location__user_has=user.id)
于 2013-03-26T12:04:00.037 回答
1

你的模型是什么样的?

出于您的疑问,__in 确实接受过滤后的 ID。

对于您当前的代码,解决方案:

locations = Location.objects.filter(id__in=has_location.objects.filter(user=user).values('location_id'))
# if you just want the length of the locations, evaluate locations.count()
locations.count()
# if you want to iterate locations to access items afterwards
len(locations)
于 2013-03-26T12:05:04.977 回答