Krishna Manohar
Krishna Manohar

Reputation: 334

Get Foreign Objects instead of QuerySet of List of ID's

single line of code to get the Foreign Key objects instead of QuerySet of UUID's.

I have three Models,

Student, College, Member

Models are defined similar to below

class Student(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name=models.CharField(max_length=128)

class College(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name=models.CharField(max_length=128)

class Member(models.Model):
    student= models.ForeignKey(Student, related_name="students", on_delete=models.CASCADE)
    college= models.ForeignKey(College, related_name="colleges", on_delete=models.CASCADE)

Where Member contains of Student and College as Foreign Key fields

Now I want to get all the Students who belong to a particular College based on college_id which should be filtered from the Member model

How I am doing now

student_ids = Member.objects.filter(college_id=college_id).values("student")

Now students is a QuerySet of list of UUID's of Student

As I need actual Student objects instead of QuerySet List of UUID's

students = Student.objects.filter(id__in=[str(uid) for uid in student_ids])

I feel this is an improper way. Can anyone suggest a single line of code to get the Foreign Key objects instead of QuerySet of UUID's. Thanks in advance

Upvotes: 1

Views: 71

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476574

You can filter with:

Student.objects.filter(students__college_id=college_id)

The related_name=… parameter [Django-doc] however is the name of the relation in reverse. It thus makes more sense to rename these for example to:

class Member(models.Model):
    student = models.ForeignKey(
        Student,
        related_name='members',
        on_delete=models.CASCADE
    )
    college = models.ForeignKey(
        College,
        related_name='members',
        on_delete=models.CASCADE
    )

then you filter with:

Student.objects.filter(members__college_id=college_id)

You can also span a conceptual ManyToManyField [Django-doc] between a College and Student:

class Student(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=128)
    colleges = models.ManyToManyField(
        'College',
        related_name='students'
        through='Member'
    )

Then you can filter with:

Student.objects.filter(colleges=college_id)

Upvotes: 2

Related Questions