【问题标题】:Django: Why don't foreign key lookups automatically use the pk?Django:为什么外键查找不自动使用pk?
【发布时间】:2010-11-11 07:21:03
【问题描述】:

我有

class Achievement(MyBaseModel):
    pass

class Alias(MyBaseModel):
    achievements = models.ManyToManyField('Achievement')

>>> ach = Achievement.objects.all()[1]

这行得通:

>>> Alias.objects.all().filter(achievements__pk__contains=ach.pk).count()
77L

但这不是:

>>> Alias.objects.all().filter(achievements__contains=ach).count()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/var/home/ptarjan/django/mysite/django/db/models/query.py", line 489, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/var/home/ptarjan/django/mysite/django/db/models/query.py", line 507, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/var/home/ptarjan/django/mysite/django/db/models/sql/query.py", line 1258, in add_q
    can_reuse=used_aliases)
  File "/var/home/ptarjan/django/mysite/django/db/models/sql/query.py", line 1201, in add_filter
    self.where.add((alias, col, field, lookup_type, value), connector)
  File "/var/home/ptarjan/django/mysite/django/db/models/sql/where.py", line 48, in add
    params = field.get_db_prep_lookup(lookup_type, value)
  File "/var/home/ptarjan/django/mysite/django/db/models/fields/related.py", line 156, in get_db_prep_lookup
    raise TypeError, "Related Field has invalid lookup: %s" % lookup_type
TypeError: Related Field has invalid lookup: contains

为什么? (Django 1.0.2)

查看查询日志,它正在做着我没想到的事情!该查询产生了:

>>> connection.queries[-1]
{'time': '0.027', 'sql': u'SELECT COUNT(*) FROM `yourock_alias` INNER JOIN `yourock_achiever` ON (`yourock_alias`.`id` = `yourock_achiever`.`alias_id`) WHERE `yourock_achiever`.`achievement_id` LIKE BINARY %j0xvw9% '}

但是这样做

>>> Alias.objects.all().filter(achievements=ach).count()
77L

给出这个查询

>>> connection.queries[-1]
{'time': '0.023', 'sql': u'SELECT COUNT(*) FROM `yourock_alias` INNER JOIN `yourock_achiever` ON (`yourock_alias`.`id` = `yourock_achiever`.`alias_id`) WHERE `yourock_achiever`.`achievement_id` = j0xvw9 '}

这是我想要的,但= 在我看来意味着它唯一的对象。如果对象在成就列表中anywhere,则 django 正在执行的查询实际上正在返回。

这是正确设置并且非常违反直觉还是我做错了什么?

【问题讨论】:

    标签: django django-models django-queryset


    【解决方案1】:

    我无法回答为什么做出设计决定以这种方式实现它,但很可能它遵循 Python 哲学,即事物应该明确指定而不是暗示。

    它不起作用的原因是因为 __contains 需要一个字段来引用。您传递给它的位是对整个对象的引用。

    【讨论】:

      【解决方案2】:

      在第二种情况下,您正在比较对象。而且,从Django documentation 开始,为了比较一个对象,您必须使用== 运算符。

      最重要的是:您为什么不使用ach.alias_set.objects.count(),正如query section of the manual 中所解释的那样?

      【讨论】:

      • 您的查询是否等效?这是推荐的方式吗? (我是 django 新手)
      • 是的。我添加了一个指向 Django 文档的链接,关于如何“向后”遵循关系。
      • 另一个原因是它永远排除了将外键设置为候选键字段(数据库中唯一的任何内容),并且排除了实现多列主键,进而排除了 Django 的ORM 在大型非平凡模式中非常有用。
      猜你喜欢
      • 1970-01-01
      • 2015-06-09
      • 2012-11-17
      • 2015-08-16
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      • 2011-01-30
      • 1970-01-01
      相关资源
      最近更新 更多