浏览代码

Fixed #30477 -- Made reverse lookup use Field.get_db_prep_value() from the target field.

can 5 年之前
父节点
当前提交
325d5d6445
共有 3 个文件被更改,包括 29 次插入14 次删除
  1. 3 2
      django/db/models/lookups.py
  2. 5 0
      tests/queries/models.py
  3. 21 12
      tests/queries/tests.py

+ 3 - 2
django/db/models/lookups.py

@@ -176,8 +176,9 @@ class FieldGetDbPrepValueMixin:
     get_db_prep_lookup_value_is_iterable = False
 
     def get_db_prep_lookup(self, value, connection):
-        # For relational fields, use the output_field of the 'field' attribute.
-        field = getattr(self.lhs.output_field, 'field', None)
+        # For relational fields, use the 'target_field' attribute of the
+        # output_field.
+        field = getattr(self.lhs.output_field, 'target_field', None)
         get_db_prep_value = getattr(field, 'get_db_prep_value', None) or self.lhs.output_field.get_db_prep_value
         return (
             '%s',

+ 5 - 0
tests/queries/models.py

@@ -67,10 +67,15 @@ class Annotation(models.Model):
         return self.name
 
 
+class DateTimePK(models.Model):
+    date = models.DateTimeField(primary_key=True, auto_now_add=True)
+
+
 class ExtraInfo(models.Model):
     info = models.CharField(max_length=100)
     note = models.ForeignKey(Note, models.CASCADE, null=True)
     value = models.IntegerField(null=True)
+    date = models.ForeignKey(DateTimePK, models.SET_NULL, null=True)
 
     class Meta:
         ordering = ['info']

+ 21 - 12
tests/queries/tests.py

@@ -16,18 +16,19 @@ from .models import (
     FK1, Annotation, Article, Author, BaseA, Book, CategoryItem,
     CategoryRelationship, Celebrity, Channel, Chapter, Child, ChildObjectA,
     Classroom, CommonMixedCaseForeignKeys, Company, Cover, CustomPk,
-    CustomPkTag, Detail, DumbCategory, Eaten, Employment, ExtraInfo, Fan, Food,
-    Identifier, Individual, Item, Job, JobResponsibilities, Join, LeafA, LeafB,
-    LoopX, LoopZ, ManagedModel, Member, MixedCaseDbColumnCategoryItem,
-    MixedCaseFieldCategoryItem, ModelA, ModelB, ModelC, ModelD, MyObject,
-    NamedCategory, Node, Note, NullableName, Number, ObjectA, ObjectB, ObjectC,
-    OneToOneCategory, Order, OrderItem, Page, Paragraph, Person, Plaything,
-    PointerA, Program, ProxyCategory, ProxyObjectA, ProxyObjectB, Ranking,
-    Related, RelatedIndividual, RelatedObject, Report, ReportComment,
-    ReservedName, Responsibility, School, SharedConnection, SimpleCategory,
-    SingleObject, SpecialCategory, Staff, StaffUser, Student, Tag, Task,
-    Teacher, Ticket21203Child, Ticket21203Parent, Ticket23605A, Ticket23605B,
-    Ticket23605C, TvChef, Valid, X,
+    CustomPkTag, DateTimePK, Detail, DumbCategory, Eaten, Employment,
+    ExtraInfo, Fan, Food, Identifier, Individual, Item, Job,
+    JobResponsibilities, Join, LeafA, LeafB, LoopX, LoopZ, ManagedModel,
+    Member, MixedCaseDbColumnCategoryItem, MixedCaseFieldCategoryItem, ModelA,
+    ModelB, ModelC, ModelD, MyObject, NamedCategory, Node, Note, NullableName,
+    Number, ObjectA, ObjectB, ObjectC, OneToOneCategory, Order, OrderItem,
+    Page, Paragraph, Person, Plaything, PointerA, Program, ProxyCategory,
+    ProxyObjectA, ProxyObjectB, Ranking, Related, RelatedIndividual,
+    RelatedObject, Report, ReportComment, ReservedName, Responsibility, School,
+    SharedConnection, SimpleCategory, SingleObject, SpecialCategory, Staff,
+    StaffUser, Student, Tag, Task, Teacher, Ticket21203Child,
+    Ticket21203Parent, Ticket23605A, Ticket23605B, Ticket23605C, TvChef, Valid,
+    X,
 )
 
 
@@ -1462,6 +1463,14 @@ class Queries4Tests(TestCase):
         CategoryItem.objects.create(category=c1)
         self.assertSequenceEqual(SimpleCategory.objects.order_by('categoryitem', 'pk'), [c1, c2, c1])
 
+    def test_filter_reverse_non_integer_pk(self):
+        date_obj = DateTimePK.objects.create()
+        extra_obj = ExtraInfo.objects.create(info='extra', date=date_obj)
+        self.assertEqual(
+            DateTimePK.objects.filter(extrainfo=extra_obj).get(),
+            date_obj,
+        )
+
     def test_ticket10181(self):
         # Avoid raising an EmptyResultSet if an inner query is probably
         # empty (and hence, not executed).