django-postgres-extra icon indicating copy to clipboard operation
django-postgres-extra copied to clipboard

Fix "*_new" suffix not being removed.

Open Veritogen opened this issue 9 months ago • 1 comments

Dear Sector Labs team,

this PR fixes an issue that occurs when we (https://github.com/einhundert) do an annotation that carries the same name as a field of the model whose queryset is being annotated. This only occurs when using PostgresManager of django-postgres-extra as a model manager.

To test the behaviour use the template: psqlextra-template.zip (includes files for using a VS Code devcontainer).

Or create a django project and a new app. Details on dependencies below. Run test without the changes to see what is actually failing. Pull the changes contained in this PR and install them using pip to see the test pass.

requirements.txt for setup:

asgiref==3.7.2
Django==4.2.4
django-postgres-extra==2.0.8
python-dateutil==2.8.2
six==1.16.0
sqlparse==0.4.4
typing_extensions==4.7.1

Paste the following content into your new apps models.py:

from django.db import models
from psqlextra.manager import PostgresManager

# Create your models here.

class Author(models.Model):
    name = models.CharField()


class BaseDataManager(PostgresManager):
    pass


class BaseBook(models.Model):

    id = models.BigAutoField(primary_key=True)
    author = models.ForeignKey(Author, null=False, on_delete=models.CASCADE) # analogue to meter
    type = models.IntegerField(choices=[("1", "Fiction"),
                                        ("2", "Fantasy")], null=False) # analogue to channel
    timestamp = models.DateTimeField(null=False) # analoge to timestamp 
    rating = models.FloatField(null=False, default=0.0) # analogue to value
    objects = BaseDataManager()

    class Meta:
        abstract = True


class Book(BaseBook):

    source = models.CharField(
        choices=[
        ("S", "self written"),
        ("G", "ghost writer"),
        ("C", "copied"),
    ],
        default="C",
        max_length=1,
        db_index=True,
    )

    class Meta:
        index_together = [["type", "author", "timestamp"], ["author", "timestamp"]]
        unique_together = ("type", "author", "timestamp", "source")
 

And the following into the tests.py:

import datetime
from random import uniform
from .models import Author, Book
import pytest
from django.db.models import Min
from django.db.models.functions.datetime import TruncMonth
from zoneinfo import ZoneInfo

@pytest.mark.django_db(True)
def test_models():
    tz = ZoneInfo("Europe/Berlin")
    author_1 = Author.objects.get_or_create(name="Author 1")[0]
    author_2 = Author.objects.get_or_create(name="Author 2")[0]
    for month in range(1, 13):
        for day in range(1, 28):
            for hour in range(0, 24):
                try:
                    Book.objects.create(author=author_1,
                                    timestamp=datetime.datetime(2023, month, day, hour, 0, tzinfo=tz),
                                    type=1,
                                    rating=uniform(0.0, 1000.0))
                    Book.objects.create(author=author_2,
                                    timestamp=datetime.datetime(2023, month, day, hour, 0, tzinfo=tz),
                                    type=2,
                                    rating=uniform(0.0, 1000.0))
                except:
                    print(month, day, hour)
    qs = Book.objects.all()
    qs = qs.filter(author__in = [author_1, author_2],
                   type__in=[1, 2]
                   )
    qs = qs.filter(timestamp__range=
                   (
        datetime.datetime(2023, 3, 15, 0, 0, tzinfo=tz), 
        datetime.datetime(2023, 7, 15, 0,0, tzinfo=tz))
        )
    qs = qs.values("author", "type").annotate(
        timestamp=TruncMonth("timestamp"), # Cause for error is here
        book_number=Min("rating"),
    ).values(
        "author",
        "type",
        "source",
        "timestamp",
        "rating",
    )
    assert len(qs) == 5184

If you need further information, feel free to reach out. Last but not least, thank you so much for putting your time and energy into this library.

Regards, Hannes Backend Developer at EINHUNDERT

Veritogen avatar Sep 15 '23 12:09 Veritogen