Django: لماذا لا تستخدم البحث عن المفتاح الأجنبي PK تلقائيا؟
-
16-09-2019 - |
سؤال
لدي
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 '}
وهو ما أردت، لكن =
يبدو لي أن يعني ذلك يكون كائن واحد. الاستعلام الذي يقوم به DJANGO هو العودة في الواقع إذا كان الكائن في أى مكان في قائمة الإنجاز.
هل هذا الإعداد بشكل صحيح وهو مجرد بديهية للغاية أو أفعل شيئا خطأ؟
المحلول
في الحالة الثانية، أنت تقارن الكائنات. و من وثائق django., ، من أجل مقارنة كائن لديك لاستخدام ==
المشغل أو العامل.
علاوة على ذلك: لماذا لا تستخدم ach.alias_set.objects.count()
, ، كما هو موضح في قسم الاستعلام من الدليل?
نصائح أخرى
لا أستطيع الإجابة عن سبب إجراء قرار التصميم لتنفيذه بهذه الطريقة، ولكن على الأرجح لمتابعة فلسفة الثعبان على أنه يجب تحديد الأمور بشكل صريح وغير ضمني.
السبب في أنه لا يعمل هو لأن __Contains تتوقع مرجع حقل. لقد مرت بت المرجع على كائن كامل.