我有名为'has_location'和'locations'的表。 'has_location'有user_has
和location_id
及其自己的id
,由django本身提供。
'locations'有更多列。
现在我想获得某些用户的所有位置。我做的是..(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
。我在db中有数据。但我觉得__in
不接受模型ID,是吗?
谢谢
答案 0 :(得分:8)
使用__in
进行此类查询是Django中常见的反模式:由于其简单性,它很诱人,但在大多数数据库中它的扩展性很差。请参阅this presentation by Christophe Pettus中的幻灯片66ff。
用户和位置之间存在多对多关系,由has_location
表表示。你通常会使用带有through
表的ManyToManyField
向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()
方法请求有效获取用户的相关位置。
答案 1 :(得分:4)
您正在使用has_location自己的ID来过滤位置。您必须使用location_id
来过滤位置:
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)
答案 2 :(得分:1)
你的模特是什么样的?
如有疑问,__in
does accept过滤了ids。
对于您当前的代码,解决方案:
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)