#python #django #annotations #django-orm
#python #django #примечания #django-orm
Вопрос:
Я пытался решить эту проблему всю неделю, но, похоже, просто не могу найти решение.
По сути, я хочу сгруппировать 2 значения (user и assignment), затем взять последний элемент на основе даты и получить сумму этих баллов. Ниже описание проблемы.
С Postgres это было бы легко решить с помощью .distinct(«значение»), но, к сожалению, я не использую Postgres.
Любая помощь будет высоко оценена!!
UserAnswer
- user
- assignment
- date
- answer
- score
Итак, я хочу сгруппировать все комбинации user / assignment. Затем я хочу получить оценку каждого последнего элемента в этой группе. Итак, в основном:
user_1, assignment_1, 2019, score 1
user_1, assignment_1, 2020, score 2 <- Take this one
user_2, assignment_1, 2020, score 1
user_2, assignment_1, 2021, score 2 <- Take this one
Моя лучшая попытка — использовать аннотацию, но тогда у меня больше нет значения score:
UserAnswer.objects.filter(user=student, assignment__in=assignments)
.values("user", "assignment")
.annotate(latest_date=Max('date'))
Комментарии:
1. как вы проверили, есть ли у вас оценка или нет? Я не вижу проблем с вашим запросом. вы проверили useranswer.score?
2. Спасибо, что подумали со мной. Я проверил его, и он возвращает только значение user, assignment и max date в нем.
Ответ №1:
В конце мне пришлось использовать необработанный запрос, а не ORM от django.
subquery2 = UserAnswer.objects.raw("
SELECT id, user_id, assignment_id, score, MAX(date) AS latest_date
FROM soforms_useranswer
GROUP BY user_id, assignment_id
")
# the raw queryset from above raw query
# is very similar to queryset you get from django ORM query.
# The difference is now we add 'id' and 'score' to the fields,
# so later we can retrieve them, like below.
sum2= 0
for obj in subquery2:
print(obj.score)
sum2 = obj.score
print('sum2 is')
print(sum2)
Здесь я предположил, что и user, и assignment являются foreinkeys . Что- то лежит внизу:
class Assignment(models.Model):
name = models.CharField(max_length=50)
class UserAnswer(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='answers')
assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
#assignment = models.CharField(max_length=200)
score = models.IntegerField()
date = models.DateTimeField(default=timezone.now)
Комментарии:
1. Хи, спасибо за ваш ответ. Я попробовал это, но, к сожалению, я по-прежнему получаю только user, assignment и lastest_date обратно в словарь. Вот так: {‘user’: 1, ‘assignment’: 1, ‘latest_date’: datetime.datetime(2020, 11, 19, 11, 0, 41, 2356, tzinfo=<UTC>)}
2. Эй, чувак, я был очень рад попробовать, но, к сожалению, похоже, это не работает :(. Агрегатная функция подсчитывает все записи, а не только lastest_date.
3. извините за ваше разочарование. Я снова обновил свой ответ. Я надеюсь, что вы можете попробовать.
4. Совсем не расстроен, мой друг 🙂 большое вам спасибо за вашу помощь. Кажется, что ваш необработанный SQL делает свое дело!