Django ProgrammingError трябва да се появи в клаузата GROUP BY или да се използва в агрегатна функция

Дайте някакъв основен модел;

class Post(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(_('Title'), max_length=100)
    content = models.TextField(_('Content html'), max_length=65000)
    author = models.ForeignKey('user.User', on_delete=models.SET_NULL)

Заявка като Post.objects.annotate(Count('id')) (или което и да е поле, any annotate()) се проваля със следната грешка:

ProgrammingError: column "post.created" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "post"."id", "post"."created", "post"."ti...

Използване на django 1.11.16 и postgres 9.4.19.

Както прочетох тук в друг въпрос за stackoverflow опитах различни версии на django и версии на postgres; използвайки django 2.0, 2.1.2, postgres 9.5.. същата грешка! Четейки наоколо, видях, че това може да е проблем, свързан със SQL, но имам този проблем само на един сървър, работещ с Ubuntu 18.04 (бионичен). Изпълнението на заявката локално в Ubuntu 16.04, с django 1.11.16 или която и да е версия над тази и postgres 9.4 или по-нова работи добре в моята локална система. Така че проблемът всъщност може да е свързан с някакво ниско ниво библиотеки може би, не изпълнявам сложни заявки, всеки прост annotate() с django 1.11+ се проваля в ubuntu 18.04 с postgres 9.4 или 9.5

[АКТУАЛИЗАЦИЯ] Може да е полезно за вас, ако попаднете в този сценарий без улики какво се случва, проверете дали въпросната таблица има създадени индекси. Проблемът ми се оказа, че таблицата posts няма PRIMARY KEY дефиниция, нито друго ограничение, грешка в pg_restore, която възстанови всички данни и някои дефиниции на схема, да, правилно прочетохте някоя друга схема дефиниции липсваха, нямам представа защо.. Но вместо да се опитам да отстраня грешката какво се случи с pg_restore на първо място, изпълних първоначален python manage migrate на празна DB, така че схемата беше правилно създадена този път и проверена (psql -d <db_name> -c '\d posts' ), след това стартирайте pg_restore отново с флаговете --data-only и --disable-triggers. Така че най-накрая възстанових правилно схемата и данните и заявката проработи


person AguD    schedule 24.10.2018    source източник
comment
Можете ли да публикувате резултата от print(Post.objects.annotate(Count('id')).query)? Това ще бъде sql заявката от вашия набор от заявки.   -  person Håken Lid    schedule 24.10.2018
comment
Няма много смисъл да се броят ids при анотиране, тъй като всеки ред съдържа един запис и следователно броят е винаги 1 (или 0 в случай на NULL.   -  person Willem Van Onsem    schedule 24.10.2018
comment
@WillemVanOnsem: Това е вярно. Но това не обяснява защо получават тази SQL грешка.   -  person Håken Lid    schedule 24.10.2018
comment
Така че заключението във въпроса, който сте свързали, е, че тази грешка е специфична за модели, поддържани от изглед на база данни вместо таблица на база данни. Ако получите този бъг само във вашата производствена база данни, трябва да проучите схемата на db и да потърсите разлики между производствената и развойната база данни.   -  person Håken Lid    schedule 24.10.2018
comment
Хей, момчета, ще актуализирам въпроса си тук; Да, доколкото разбирам за сега, GROUP BY само ID без препратка към другите полета на SELECT работи, ако всъщност имате индекс на ID.. се оказва, че след pg_restore по някаква странна причина (която не успях разкриване) данните бяха възстановени, но някои (не всички) дефиниции на схема липсваха.. така че таблицата с публикации например нямаше оператор PRIMARY KEY и по този начин анотирането е неуспешно   -  person AguD    schedule 25.10.2018
comment
[АКТУАЛИЗАЦИЯТА] работи за мен.   -  person amolbk    schedule 26.07.2021


Отговори (2)


Това съобщение за грешка е, защото PostgreSQL няма да направи предположение какво да прави с негрупираните колони, когато в заявката има агрегатна функция. Това е един от случаите, в които Django ORM маха твърде много и ни позволява да се простреляме в крака.

Проведох тест на моите проекти, които използват Django 2.1 и друг, който използва 1.11 с Model.objects.annotate(Count('id')) без проблеми. Ако публикувате пълния QuerySet, хората ще могат да ви помогнат допълнително.

person schillingt    schedule 24.10.2018
comment
Благодаря @schillingt! Да, понякога наличието на твърде много магия в абстракционен слой прави отстраняването на грешки в ъглови случаи по-сложно :/ Реших какъв е проблемът, таблицата нямаше схема при възстановяване на дъмп с pg_restore, данните бяха там, но таблицата нямаше индекси, без ограничения, първични ключове.. Това беше проблемът, причиняващ неуспех на заявката тук, защо pg_restore не успя да възстанови схемата на някои* (не всички) таблици.. нямам идея.. Измислих заобиколно решение и тръгнах по този начин, преди да опитам да отстраня грешки pg_restore - person AguD; 25.10.2018

Срещнах проблема и го реших. трябва да добавите .order_by("xxx") следвайте вашия ORM!

преди:

search_models.Author.objects.values("first_institution", 'institution_code').annotate(counts=Count('first_institution'))

след:

search_models.Author.objects.values("first_institution", 'institution_code').annotate(counts=Count('first_institution')).order_by('-counts')

При мен проработи, също и wish може да ти помогне.

person bode liang    schedule 08.06.2021