Selecting primary key in 5.2

Hello, unsure if this counts a regression or not so I thought I would check here. Normally you would not care about the raw SQL produced by the ORM. But after upgrading from 5.1.7 to 5.2.0 some queries using a third party library (django_cte) failed because it tries to join on the meta field “pk” which normally resolves to “id”.
Minimal example of the changed behavior:

from django.conf import settings
settings.configure(
    INSTALLED_APPS=['django.contrib.contenttypes'],
    DATABASES={'default':{'ENGINE':'django.db.backends.sqlite3','NAME':':memory:'}}
)
import django
django.setup()
from django.contrib.contenttypes.models import ContentType
print(ContentType.objects.values("pk").query)

Running the example on 5.1.7 and 5.2.0:

$ uv run --with 'django==5.1.7' example.py 
SELECT "django_content_type"."id" FROM "django_content_type"
$ uv run --with 'django==5.2.0' example.py 
SELECT "django_content_type"."id" AS "pk" FROM "django_content_type"

For my specific use case the simple fix is to select “id” instead of “pk”. But I still wonder if this is as designed?

Hello @simwr872!

I can confirm the change is as intended and that Django doesn’t provide guarantee as to what SQL gets generated while it tries to maintain backward compatiblity as much as possible.

For this particular case of id being aliases to pk it could potentially be adjusted to restore its previous behaviour but I suspect that if django-cte breaks in this case it will break in a few non-trivial ones where a column with the same name (same table or not) is present twice in the query so there are likely adjustments they need to make on their side in all cases.

I’d suggest opening an issue with the third party package and see if there is anything they can do to internally but without a complete example of it in action neither I or them will be able to assess the situation fully. I suspect the problem relates to this issue that can now be solved by introspecting sql.Query.selected which was introduced in Django 5.2.

For context, this change was made to provide finer grained control over the SELECT clause generation logic to ease the UNION of complex query mixing field references with annotations.

2 Likes

Thank you. For anyone interested, I have opened a pull request in django-cte with a proposed fix to support Django 5.2.

1 Like