Douglas da Dias Silva
Douglas da Dias Silva

Reputation: 1230

Is it possible access an attribute of another model via queryset?

I need to display in a page a list with the candidates for their respective averages, the candidates' scores for the calculation of the average are in another model (Evaluation), this model receives an attribute score that contains the note of that evaluation that the candidate received and a foreign key with the candidate, so there may be several "Evaluation" with the same candidate, I have to display all the candidates with their respective averages, however the "Candidate" template does not have access to the notes, since they are stored in the Template "Evaluation", I then thought to make a for that would take the candidates of a queryset obj.all with the candidates and make the calculation of the average according to the current result, within a loop for in "Evaluation.objects.all ( ) ", Then after passing the candidate and his average to a dictionary that was placed in an array, so far so good, it works perfectly, however I need to make when clicking the candidate the user is to redirect (Name and other information) but to use "pk" I want queryset, not for certain dictionaries? So, what is my problem, I also tried queryset within the "Evaluation" template, but I can not access "Evaluation.objects.all ()" from within the "Evaluation" template itself to do the collection of 'score' and take the average, I really do not know what to do here, what do you suggest?

models.py

from django.db import models
from jsonfield import JSONField
from site_.settings import MEDIA_ROOT
from django.core.validators import MaxValueValidator

class Criterion(models.Model):
    label = models.CharField(max_length=100)

    def  __str__(self):
        return self.label

class Candidate(models.Model):
    name = models.CharField(max_length=100)
    e_mail = models.EmailField(max_length=100, default = '')
    github = models.URLField(default = '')
    linkedin = models.URLField(max_length=100, default = '')
    cover_letter = models.TextField(default = '')
    higher_education = models.BooleanField(default = False)
    docfile = models.FileField(upload_to='/home/douglas/Documentos/Django/my-second-blog/site_/media', null=True, blank=True)



    def  __str__(self):
        return self.name


class Evaluation(models.Model):
    candidate = models.ForeignKey(Candidate)
    criterion = models.ForeignKey(Criterion, default='')
    score = models.PositiveIntegerField(default = 0, validators=[MaxValueValidator(10)])
    appraiser = models.ForeignKey('auth.User')

    def  __str__(self):
        return str(self.candidate)

#model de teste
class Teste(models.Model):
    nome = models.CharField(max_length=10)

    def  __str__(self):
        return str(self.nome)

views.py

from django.shortcuts import render, get_object_or_404
from .models import Candidate, Criterion, Evaluation
from django import forms
from .forms import CandForm
from .forms import EvalForm
from .forms import TestForm
from django.shortcuts import redirect
from django.db import IntegrityError
import re


def canditate_list(request):
    candidates = Candidate.objects.all()
    evaluation = Evaluation.objects.all()

    context = {
        'candidates': candidates,
        'evaluation': evaluation,
    }
    return render(request, 'app/candidate_list.html',context)

def candidate_detail(request, pk):
    candidate = get_object_or_404(Candidate, pk=pk)
    c_name = candidate.name                                 #pega o nome (string) do candidato
    c1 = Evaluation.objects.all()                           #guarda tds Evaluation na variavel  
    scores = []                                             #declara a array que vai receber as notas
    for c in c1:                                            
        cand = str(c.candidate)                             #guarda o nome do candidato do Evaluation atual
        if cand == c_name:                                  #confere se o Evaluation atual corresponde ao candidate atual(pk)
            scores += [c.score]

    soma = 0                                                #variavel que guardara a soma declarada
    for s in scores:
        soma += s                                           #faz a soma dos scores

    average = 0 
    if len(scores) > 0:
        average = soma/len(scores)                              #tira a média

    context = {
        'candidate': candidate,
        'average': average,
    }

    return render(request, 'app/candidate_detail.html', context)

html

{% load staticfiles %}
{% load mathfilters %}
<!DOCTYPE html>
<html>
<head>
    <title>Lista de candidatos</title>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
    <link href="https://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css"> 
    <link href="{% static 'css/app.css' %}" rel="stylesheet">   
</head>
<body>
    <h1 class="h1t">Lista de Candidatos</h1>
    {% for l in candidates %}
        <p class="tr"><a href="{% url 'candidate_detail' l.pk %}">{{l}}</a></p>
    {% endfor %}

</body>
</html>

Upvotes: 0

Views: 43

Answers (1)

itzMEonTV
itzMEonTV

Reputation: 20339

You can do

from django.db.models import Avg

candidate = get_object_or_404(Candidate, pk=pk)
average = Evaluation.objects.filter(candidate= candidate).aggregate(Avg('score'))['score__avg']

Upvotes: 1

Related Questions