Reputation: 682
If I had a model structure like this:
class Camp(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=200, blank=True, null=True)
reg_start = models.DateTimeField()
reg_end = models.DateTimeField()
class Course(models.Model):
camp = models.ForeignKey(Camp, on_delete=models.PROTECT)
name = models.CharField(max_length=100)
description = models.CharField(max_length=500, blank=True, null=True)
class ClassDetail(models.Model):
course = models.ForeignKey(Course, on_delete=models.PROTECT)
seat_count = models.IntegerField()
limit_registrations = models.BooleanField(default=False)
class Registration(models.Model):
person = models.ForeignKey(User, on_delete=models.PROTECT)
class_detail = models.ForeignKey(CourseDetail, on_delete=models.PROTECT)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
If I had a user that had (potentially) multiple Registrations
, is there a quick and easy way to get a list of the id's of those camps?
This is what I currently have (which is working but I'm trying to see if I can eliminate the list comprehension)
registration_queryset = Registration.objects.filter(
person__id=user_id
)
camps_to_exclude = [
x.course_detail.course.camp.id for x in registration_queryset
]
# camp_list is an already existing queryset of camps
camp_list = camp_list.exclude(
id__in=camps_to_exclude,
)
Upvotes: 0
Views: 24
Reputation: 13731
Here's one option. As long as they are querysets, django will reduce them into a single query. You can always check the query with print(queryset.query)
.
camp_list.exclude(
id__in=registration_queryset.values_list('course_detail__course__camp__id', flat=True),
)
Or you can do:
camp_list.exclude(
course_set__classdetail_set__registration_set__person_id=user_id
).distinct()
The distinct will be necessary since you're crossing a pair of reverse foreign keys.
Upvotes: 1