Django - Агрегировать с регистром, где значения не из базы данных - PullRequest
0 голосов
/ 16 апреля 2020

Позвольте мне начать с того, что: Да, я знаю, что могу просто сохранить рейтинги как числа в своей базе данных, и я знаю, что так будет намного проще. Тем не менее, если бы я делал это таким образом (я, скорее всего, не должен быть, но я есть), поэтому я хочу решить это с текущей настройкой, как есть, только с возможностью настройки свойства rating_point, если это возможно.

utils.models.Choices, по сути, является оберткой для обычных python словарей, может также поделиться этим при необходимости.

Попытка сохранить код как можно более чистым, и я показываю вам все как можно меньше, чтобы избежать путаницы, все еще кажется большим, но я думаю, что все должно быть здесь, чтобы легко отладить его.

from django.db import models
from django.db.models import Avg, When, Case, Value
from mptt.models import TreeForeignKey
from utils.models import Choices


class Product(CommonFields, ProductRelatedMixin):
    @property
    def rating_point(self):
        comment = self.comments.model
        return self.comments.aggregate(
            whatever=Avg(
                Case(
                    *[
                        When(
                            rating=rating,
                            then=Value(comment.rating_points_map.get(rating))
                        ) for rating in comment.ratings.choices
                    ],
                    output_field=models.IntegerField()
                )
            )
        )


class Comment(CommonFields):
    ratings = Choices(
        POOR="POOR",
        OKAY="OKAY",
        GOOD="GOOD",
        AMAZING="AMAZING",
        EXCELLENT="EXCELLENT",
    )

    rating_points_map = {
        ratings.POOR: 1,
        ratings.OKAY: 2,
        ratings.GOOD: 3,
        ratings.AMAZING: 4,
        ratings.EXCELLENT: 5,
    }

    user = models.ForeignKey('User', on_delete=models.CASCADE, related_name='comments')
    product = models.ForeignKey('Product', on_delete=models.CASCADE, related_name='comments')
    rating = models.CharField(
        max_length=20,
        choices=ratings.choices,
    )

    @property
    def rating_point(self):
        return self.rating_points_map.get(self.rating)


The above exception was the direct cause of the following exception:

# Traceback (most recent call last):
#   File "<console>", line 1, in <module>
#   File "C:\Users\isik\Desktop\projects\p\p\p\apps\core\models\product.py", line 122, in rating_point
#     return self.comments.aggregate(
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
#     return getattr(self.get_queryset(), name)(*args, **kwargs)
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\models\query.py", line 384, in aggregate
#     return query.get_aggregation(self.db, kwargs)
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\models\sql\query.py", line 502, in get_aggregation
#     result = compiler.execute_sql(SINGLE)
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\models\sql\compiler.py", line 1151, in execute_sql
#     cursor.execute(sql, params)
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\backends\utils.py", line 100, in execute
#     return super().execute(sql, params)
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\backends\utils.py", line 68, in execute
#     return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\backends\utils.py", line 77, in _execute_with_wrappers
#     return executor(sql, params, many, context)
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\backends\utils.py", line 86, in _execute
#     return self.cursor.execute(sql, params)
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\utils.py", line 90, in __exit__
#     raise dj_exc_value.with_traceback(traceback) from exc_value
#   File "C:\Users\isik\.virtualenvs\p\lib\site-packages\django\db\backends\utils.py", line 86, in _execute
#     return self.cursor.execute(sql, params)
# django.db.utils.ProgrammingError: function avg(text) does not exist
# LINE 1: SELECT AVG(CASE WHEN "core_comment"."rating" = '(''POOR'', '...
#                ^
# HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

1 Ответ

0 голосов
/ 16 апреля 2020

Хорошо, так что, видимо, я не сделал свой utils.models.Choices класс повторяемым; после превращения его в итеративный; все работало без сбоев.

...