【问题标题】:django model object filterdjango模型对象过滤器
【发布时间】:2013-03-16 05:11:36
【问题描述】:

我有名为“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)

但我通过这个print 得到0。我在数据库中有数据。但我感觉__in 不接受models id,是吗?

谢谢

【问题讨论】:

  • 你能告诉我们这三个模型定义的相关部分吗?
  • @GarethRees,当然,但它们只是普通模型。我认为,这里的重点更多是关于我可以使用 __in 的内容。

标签: python database django django-forms


【解决方案1】:

您正在使用 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)

【讨论】:

    【解决方案2】:

    您的模型是什么样的?

    对于您的疑问,__indoes accept 过滤的 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)
    

    【讨论】:

      【解决方案3】:

      使用__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() 方法请求有效地获取用户的相关位置。

      【讨论】:

      • 哇,非常好。我的数据库知识很差,非常有用的指导,非常感谢。
      • 如果您正在编写 Django 应用程序,那么绝对值得学习有关数据库的知识。 (否则有一天你会发现你的应用程序运行得太慢了,你不知道如何解决它。)一个好的第一步是在你的数据库中打开查询日志并在你测试你的 Django 站点时监控日志查看实际正在执行的查询。
      猜你喜欢
      • 2016-05-17
      • 2020-07-02
      • 1970-01-01
      • 2014-08-22
      • 1970-01-01
      • 2012-03-13
      • 2019-12-27
      相关资源
      最近更新 更多