Как аннотировать / агрегировать строковые поля в Django - PullRequest
1 голос
/ 24 января 2012

У меня есть сложный набор данных, который, если исходить из необработанного SQL, будет включать много объединений и делать странные вещи, такие как использование функций-агрегаторов для строковых полей:

SELECT
    "trainer_trainer"."user_id",
    "trainer_trainer"."email",
    "trainer_trainer"."background",
    "trainer_trainer"."history",
    "trainer_trainer"."manualrating",
    COUNT("trainer_helperqueue"."id") AS "available",
    MAX("account_account"."photo") AS "photo",
    COUNT("trainer_trainersession"."id") AS "busy",
    MAX("account_account"."name") AS "name"
FROM
    "trainer_trainer"
LEFT OUTER JOIN
    "auth_user" ON ("trainer_trainer"."user_id" = "auth_user"."id")
LEFT OUTER JOIN
    "trainer_helperqueue" ON ("auth_user"."id" = "trainer_helperqueue"."user_id")
LEFT OUTER JOIN
    "account_account" ON ("auth_user"."id" = "account_account"."user_id")
LEFT OUTER JOIN
    "trainer_trainersession" ON ("auth_user"."id" = "trainer_trainersession"."helper_id")
GROUP BY
    "trainer_trainer"."user_id",
    "trainer_trainer"."email",
    "trainer_trainer"."background",
    "trainer_trainer"."history",
    "trainer_trainer"."manualrating",
    "trainer_trainer"."user_id",
    "trainer_trainer"."email",
    "trainer_trainer"."background",
    "trainer_trainer"."history",
    "trainer_trainer"."manualrating"

Этот запрос на самом деле работает довольно хорошо, но Django взрывается внутри, когда пытается обработать результаты:

Trainer.objects.annotate(
    photo=Max("user__account__photo"),
    name=Max("user__account__name"),
    available=Count("user__assistance_providing"),
    busy=Count("user__helping")
)

ValueError: invalid literal for float(): path/to/photo.jpg

Вот конец трассировки:

PROJECTROOT/virtualenv/lib/python2.6/site-packages/django/db/models/sql/compiler.pyc in results_iter(self)
    705                         for (alias, aggregate), value
    706                         in zip(self.query.aggregate_select.items(), row[aggregate_start:aggregate_end])
    --> 707                     ]) + tuple(row[aggregate_end:])
    708 
    709                 yield row

PROJECTROOT/virtualenv/lib/python2.6/site-packages/django/db/models/sql/query.pyc in resolve_aggregate(self, value, aggregate, connection)
    320         else:
    321             # Return value depends on the type of the field being processed.

--> 322             return self.convert_values(value, aggregate.field, connection)
    323 
    324     def get_aggregation(self, using):

PROJECTROOT/virtualenv/lib/python2.6/site-packages/django/db/models/sql/query.pyc in convert_values(self, value, field, connection)
    298         it can be overridden by Query classes for specific backends.
    299         """
--> 300         return connection.ops.convert_values(value, field)
    301 
    302     def resolve_aggregate(self, value, aggregate, connection):

PROJECTROOT/virtualenv/lib/python2.6/site-packages/django/db/backends/__init__.pyc in convert_values(self, value, field)
    742         # No field, or the field isn't known to be a decimal or integer

    743         # Default to a float

--> 744         return float(value)
    745 
    746     def check_aggregate_support(self, aggregate_func):

ValueError: недопустимый литерал для float (): photos / 4/8/7 / 20120124111455-487767.jpg

Странно то, что SQL-запрос прямо здесь? Тянет прямо с db.connection.queries. Джанго запустил его, он работал на уровне базы данных, а затем Джанго отключился, обрабатывая результаты.

Должен ли я просто не использовать .annotate() с нечисловыми функциями? Есть ли лучший / умный способ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...