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