Запрос Django, который объединяет две модели и находит среднее значение оценок

В моей модели есть некоторые Тесты в Tests модели,

в каждом тесте есть несколько вопросов, которые представлены в модели Question,

и некоторые типы относятся к каждому тесту, которые находятся в модели TestTypes,

и есть модель QuestionResult, которая сохраняет оценки каждого теста:

Вот эти модели :

Test :

class Test(BaseModel):
    class DifficultyLevel(models.IntegerChoices):
        EASY = 1
        MEDIUM = 2
        HARD = 3

    types = models.ManyToManyField(
        'TestType',
        related_name='tests',
    )
    questions = models.ManyToManyField(
        'question.Question',
        related_name='tests',
        blank=True,
        help_text='Standard tests could have multiple questions.',
    )


    level = models.IntegerField(default=1, choices=DifficultyLevel.choices)

    title = models.CharField(max_length=255)
    
    def __str__(self):
        return self.title

Вопрос:


class Question(BaseModel):
  
    question_text = models.TextField()

    def __str__(self):
        return truncatewords(self.question_text, 7)

TestResult :


class TestResult(BaseModel):
 
    candidate = models.ForeignKey(
        'Candidate',
        on_delete=models.CASCADE,
        related_name='test_results',
    )

    test = models.ForeignKey(
        'exam.Test',
        on_delete=models.CASCADE,
    )

    test_score = models.DecimalField(default=0.00, max_digits=5, decimal_places=2)

    def __str__(self):
        return f'{self.candidate.user.email} - {self.test.title}'

TestType :

class TestType(BaseModel):
    title = models.CharField(max_length=255)

    def __str__(self):
        return self.title

теперь я хочу получить оценку, которую заработал каждый тип

например, тест1 получил оценку =90 и тест1 имеет два типа : HTML и C++ .

Тест2 получил оценку = 50 и тест2 имеет два типа : HTML и Python

теперь я хочу найти оценку, которую получил тип HTML, которая должна быть (90+50)/2=70

как мне написать запрос?

Это может помочь вам, так как вам нужно несколько подзапросов в вашем коде Вот документация по подзапросам в django Subquery

test_type_scores = TestResult.objects.filter(test__types=OuterRef('pk')).annotate(
    avg_score=Avg('test_score')
)

# Then, get the test types and their average scores
test_types = TestType.objects.annotate(
    avg_score=Subquery(test_type_scores.values('avg_score')[:1])
).values('title', 'avg_score')

# You can then use this queryset to get the scores for each test type
test_types = list(test_types)
print(test_types)

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

Например, если вы хотите получить оценку для типа теста HTML, вы можете сделать:

html_score = next(t['avg_score'] for t in test_types if t['title'] == 'HTML')
print(html_score)  # 70.0
Вернуться на верх