Giorgio Scarso
Giorgio Scarso

Reputation: 418

Single object from queryset

I need help with a little issue I am having with my project. I have a model where I have a foreign key with many entries and I would like to take just one item of these entries. In fact, my problem is something like that: I need to obtain the single mission id, in order to have other functions. The code is working fine, my problem is that I don't know the righe order to obtain the mission item from this queryset:

models.py

from django.db import models

from flight.models import LogEntry
from user.models import Instructor, Student

# Create your models here.


TRAINING_COURSE_CHOICES = (
    ('PPL', 'PPL'),
    ('CPL', 'CPL'),
    ('IR', 'IR'),
    ('ATPL', 'ATPL'),
)


class TrainingCourse(models.Model):
    name = models.CharField(max_length=20, choices=TRAINING_COURSE_CHOICES)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name


class StudentTrainingCourse(models.Model):
    training_course = models.ForeignKey(
        TrainingCourse, on_delete=models.PROTECT)
    student = models.ForeignKey(Student, on_delete=models.PROTECT)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.student.first_name + ' ' + self.student.last_name + ' ' + self.training_course.name


class Mission(models.Model):
    name = models.CharField(max_length=200)
    training_course = models.ForeignKey(
        TrainingCourse, on_delete=models.CASCADE)
    note = models.TextField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.training_course.name + ' ' + self.name


class StudentMission(models.Model):
    mission = models.ForeignKey(Mission, on_delete=models.PROTECT)
    student_training_course = models.ForeignKey(
        StudentTrainingCourse, on_delete=models.PROTECT)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['mission__name']

    def __str__(self):
        return self.mission.name


class LearningObjective(models.Model):
    name = models.CharField(max_length=300)
    mission = models.ForeignKey(Mission, on_delete=models.DO_NOTHING)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name


GRADING_VALUE = (
    ('1', '1'),
    ('2', '2'),
    ('3', '3'),
    ('4', '4'),
    ('5', '5'),
)


class MissionEntry(models.Model):
    student = models.ForeignKey(
        Student, on_delete=models.DO_NOTHING, blank=True, null=True)
    mission = models.ForeignKey(
        Mission, on_delete=models.DO_NOTHING, null=True, blank=True)
    log_entry = models.ForeignKey(
        LogEntry, on_delete=models.DO_NOTHING, blank=True, null=True)
    learning_objective = models.ForeignKey(
        LearningObjective, on_delete=models.DO_NOTHING, blank=True, null=True)
    grade = models.CharField(
        max_length=10, choices=GRADING_VALUE, blank=True, null=True)
    note = models.TextField(blank=True, null=True)
    debriefing = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return str(self.mission) + ' ' + str(self.log_entry)

    class Meta:
        verbose_name_plural = 'Mission Entries'


class MissionEntryStatus(models.Model):
    student_mission = models.ForeignKey(
        StudentMission, on_delete=models.PROTECT, null=True, blank=True)
    mission = models.ForeignKey(
        Mission, on_delete=models.PROTECT, null=True, blank=True)
    student = models.ForeignKey(Student, on_delete=models.PROTECT)
    is_completed = models.BooleanField(default=False)
    is_failed = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

views.py

def student_mission_list(request, pk):
    student = Student.objects.get(id=pk)
    student_training_course = StudentTrainingCourse.objects.get(
        student_id=student)

    missions = StudentMission.objects.filter(
        student_training_course_id=student_training_course)

    context = {
        'student': student,
        'missions': missions,
    }
    return render(request, 'mission/student_mission_list.html', context)

In fact, in student_mission_list I need to retrieve the mission_id!!! The problem is that, if I try to retrieve that from StudentTraining or MissionEntryStatus model, I have multiple missions; but i'd like to have just the corresponding mission_id, but I am not able to find a way. Is there any suggestion? Probably I have to modify the database, but I don't know where. Thank you very much to all of you for your help

Upvotes: 1

Views: 176

Answers (1)

raphael
raphael

Reputation: 2880

The way you have it set up now, a StudentTrainingCourse can have only ONE student but, because a ForeignKey is a ManyToOne relationship, MANY students can have that same StudentTrainingCourse. What I think you want is for a Student to have ONE StudentTrainingCourse, but a StudentTrainingCourse to have MANY Students. My guess is what you need is:

class Student(models.Model):
    ...

    training_course = models.ForeignKey(StudentTrainingCourse, on_delete=models.CASCADE)
    
    ...

Then you can get the particular mission id like:

def student_mission_list(request, pk):
    student = Student.objects.get(id=pk)
    training_course = student.training_course
    mission = Mission.objects.get(training_course=training_course)
    # If you just want the mission ID:
    mission_id = mission.pk

    missions = StudentMission.objects.filter(
        student_training_course_id=student_training_course)

    context = {
        'student': student,
        'missions': missions,
    }
    return render(request, 'mission/student_mission_list.html', context)
    

Upvotes: 1

Related Questions