Foreach Ответ вычисляет количество баллов
У меня есть набор анкет, в каждой из которых есть вопросы, и каждый вопрос имеет ответ, значение ответа и вес ответа.
Нужно получить каждый ответ и умножить ответ value.count
на answer weight value
Например, вопрос, 1 значение ответа --
, которому присваивается значение -2
и вес 20
, поэтому мне нужно рассчитать -2 x 20
и так далее для каждого вопроса, чтобы получить общий балл всех вопросов анкеты.
Мой взгляд на сегодняшний день
questionnaires = ProjectQuestionnaire.objects.all()
results = []
for q in questionnaires:
if ProjectQuestionnaireResponse.objects.filter(project_name_id=project_id, questionnaire_id = q.id).exists():
q_response = ProjectQuestionnaireResponse.objects.get(project_name_id=project_id, questionnaire_id = q.id)
q_answered = ProjectQuestionnaireAnswer.objects.filter(response = q_response, answer__isnull=False).count()
if q_answered > 1:
q_count = (100 / ProjectQuestionnaireQuestion.objects.filter(questionnaire_id = q.id).count() * q_answered)
else:
q_count = 0
###### Trying to calculate here ######
the_score = []
for answer in q_answered:
answer_score = ProjectQuestionnaireAnswer.objects.filter()
###### END of Calculation ######
Модели:
class ProjectQuestionnaire(models.Model):
title = models.CharField(max_length=50, blank=False, unique=True)
description = models.TextField(blank=True)
def __str__(self):
return str(self.title)
class ProjectQuestionnaireQuestion(models.Model):
questionnaire = models.ForeignKey(ProjectQuestionnaire, on_delete=models.CASCADE)
sequence = models.IntegerField()
question = models.TextField()
description = models.TextField(blank=True)
def __str__(self):
return str(self.question)
class ProjectQuestionnaireResponse(models.Model):
project_name = models.ForeignKey(Project, on_delete=models.CASCADE)
questionnaire = models.ForeignKey(ProjectQuestionnaire, on_delete=models.CASCADE)
user = models.CharField(max_length=50, blank=True)
class Meta:
constraints = [
models.UniqueConstraint(fields= ['project_name','questionnaire'], name='project_unique_response1'),
]
def __str__(self):
return str(self.project_name)
class Choice(models.Model):
question = models.ForeignKey(ProjectQuestionnaireQuestion, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
choice_value = models.CharField(max_length=20, blank=True)
choice_weight = models.IntegerField(blank=True, null=True)
def __str__(self):
return str(self.choice_text)
class ProjectQuestionnaireAnswer(models.Model):
YN_Choices = [
('Yes', 'Yes'),
('No', 'No'),
('Unknown', 'Unknown')
]
question = models.ForeignKey(ProjectQuestionnaireQuestion, on_delete=models.CASCADE)
answer = models.ForeignKey(Choice, on_delete=models.CASCADE,null=True)
value = models.CharField(max_length=20, blank=True)
notes = models.TextField(blank=True)
response = models.ForeignKey(ProjectQuestionnaireResponse, on_delete=models.CASCADE)
class Meta:
constraints = [
models.UniqueConstraint(fields=['question','response'], name='project_unique_response2'),
]
def __str__(self):
return str(self.answer)
Я бы предложил добавить метод или свойство к модели. Вы могли бы повторно использовать расчет баллов в любом месте, где вы работаете с моделями.
choice_value_to_score_map = {
'--': -2,
'-': -1,
'o': 0,
'+': 1,
'++': 2,
}
class ProjectQuestionnaireAnswer(models.Model):
# your existing code ...
@property
def score(self):
if not self.value:
return None # or maybe 0, this depends on how you like to calculate
for choice in self.question.choice_set.all():
if choice.value == self.value:
return choice_value_to_score_map.get(self.value, 0) * choice.choice_weight
return None # or maybe 0, this depends on how you like to calculate
Или вы можете добавить свойство к Choice
, чтобы получить оценку выбора, если нет необходимости включать Answer
в расчет.
choice_value_to_score_map = {
'--': -2,
'-': -1,
'o': 0,
'+': 1,
'++': 2,
}
class Choice(models.Model):
question = models.ForeignKey(ProjectQuestionnaireQuestion, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
choice_value = models.CharField(max_length=20, blank=True)
choice_weight = models.IntegerField(blank=True, null=True)
def __str__(self):
return str(self.choice_text)
@property
def raw_score(self):
if not self.value:
return 0
return choice_value_to_score_map.get(self.value, 0)
@property
def weighted_score(self):
return self.raw_score * self.choice_weight
class ProjectQuestionnaireAnswer(models.Model):
# your existing code ...
@property
def score(self):
if not self.value:
return None # or maybe 0, this depends on how you like to calculate
for choice in self.question.choice_set.all():
if choice.value == self.value:
return choice.weighted_score
return None # or maybe 0, this depends on how you like to calculate