Commit 05c7129b authored by Matt Johnson's avatar Matt Johnson Committed by Tim Graham
Browse files

[1.8.x] Fixed #12768 -- Fixed QuerySet.raw() regression on FK with custom db_column.

Backport of e063ac2f from master
parent ca13fb02
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1267,11 +1267,11 @@ class RawQuerySet(object):
        """
        Resolve the init field names and value positions
        """
        model_init_names = [f.attname for f in self.model._meta.fields
                            if f.attname in self.columns]
        model_init_fields = [f for f in self.model._meta.fields if f.column in self.columns]
        annotation_fields = [(column, pos) for pos, column in enumerate(self.columns)
                             if column not in self.model_fields]
        model_init_order = [self.columns.index(fname) for fname in model_init_names]
        model_init_order = [self.columns.index(f.column) for f in model_init_fields]
        model_init_names = [f.attname for f in model_init_fields]
        return model_init_names, model_init_order, annotation_fields

    def __iter__(self):
+4 −0
Original line number Diff line number Diff line
@@ -14,3 +14,7 @@ Bugfixes

* Added a system check warning if the old ``TEMPLATE_*`` settings are defined
  in addition to the new ``TEMPLATES`` setting.

* Fixed ``QuerySet.raw()`` so ``InvalidQuery`` is not raised when using the
  ``db_column`` name of a ``ForeignKey`` field with ``primary_key=True``
  (:ticket:`12768`).
+4 −0
Original line number Diff line number Diff line
@@ -23,6 +23,10 @@ class Book(models.Model):
    opening_line = models.TextField()


class BookFkAsPk(models.Model):
    book = models.ForeignKey(Book, primary_key=True, db_column="not_the_default")


class Coffee(models.Model):
    brand = models.CharField(max_length=255, db_column="name")

+13 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ from datetime import date
from django.db.models.query_utils import InvalidQuery
from django.test import TestCase, skipUnlessDBFeature

from .models import Author, Book, Coffee, FriendlyAuthor, Reviewer
from .models import Author, Book, BookFkAsPk, Coffee, FriendlyAuthor, Reviewer


class RawQueryTests(TestCase):
@@ -259,3 +259,15 @@ class RawQueryTests(TestCase):
            list(Book.objects.raw('SELECT id FROM (SELECT * FROM raw_query_book WHERE paperback IS NOT NULL) sq'))
        except InvalidQuery:
            self.fail("Using a subquery in a RawQuerySet raised InvalidQuery")

    def test_db_column_name_is_used_in_raw_query(self):
        """
        Regression test that ensures the `column` attribute on the field is
        used to generate the list of fields included in the query, as opposed
        to the `attname`. This is important when the primary key is a
        ForeignKey field because `attname` and `column` are not necessarily the
        same.
        """
        b1 = Book.objects.latest('id')
        b = BookFkAsPk.objects.create(book=b1)
        self.assertEqual(list(BookFkAsPk.objects.raw('SELECT not_the_default FROM raw_query_bookfkaspk')), [b])