SectorLabs / django-postgres-extra

Bringing all of PostgreSQL's awesomeness to Django.
MIT License
695 stars 96 forks source link

backward incompatible to models.QuerySet - KeyError when alias expression to existing field #226

Closed ivan-klass closed 3 months ago

ivan-klass commented 11 months ago

In certain conditions PostgresQuerySet behaves differently and raises KeyError where django QuerySet doesn't.

In example below, when using named expressions in .values clause after .distinct() and one of the names shadows an existing column (id) - a KeyError is observed

File ~/.pyenv/versions/example/lib/python3.11/site-packages/django/db/models/sql/query.py:2444, in Query.set_values(self, fields)
   2442 for expr in self.group_by:
   2443     if isinstance(expr, Ref) and expr.refs not in selected:
-> 2444         expr = self.annotations[expr.refs]
   2445     group_by.append(expr)
   2446 self.group_by = tuple(group_by)

KeyError: 'id_new'
from django.conf import settings
from django.db import models
from psqlextra.query import PostgresQuerySet

class Example(models.Model):

    foo = models.CharField()
    bar = models.CharField()
    baz = models.CharField()

    objects = models.QuerySet.as_manager()
    pg_objects = PostgresQuerySet.as_manager()

    class Meta:
        app_label = "whatever"

def reassign_alias(manager):
    return sorted(
        manager.values("foo").distinct().values(max_bar=models.Max("bar"), id=models.F("baz")),
        key=lambda r: r["id"]
    )

def test():
    default = reassign_alias(Example.objects)
    pg = reassign_alias(Example.pg_objects)  # KeyError
    assert default == pg

python - 3.11 django - 4.2.7 django-postgres-extra - 2.0.8

Veritogen commented 10 months ago

@ivan-klass I opened a PR as we ran into a similar issue: https://github.com/SectorLabs/django-postgres-extra/pull/222 Maybe it solves your issue too.

Photonios commented 3 months ago

This was resolved in this PR: A fix was merged for this here: https://github.com/SectorLabs/django-postgres-extra/pull/236