django-postgres-extra
django-postgres-extra copied to clipboard
Fix "*_new" suffix not being removed.
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