Reputation: 468
The use case is the following: I'm trying to retrieve all Prospects that were generated under a Manager. The models are as follow: Prospect <---> Appointment <---> Staff <---> Manager. As you can see, there is no direct relationship between a prospect and a manager so I'm forced to do a nested, reverse lookup through the other models.
For example, I try to retrieve the prospects generated under Manager id=2 through the following query:
Prospect.objects.filter(appointment=Appointment.objects.filter(staff__manager=Manager.objects.get(user=2)))
But then I get the following error:
ValueError: The QuerySet value for an exact lookup must be limited to one result using slicing.
Any hint about what's wrong with my query?
Models.py
class Prospect(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField(max_length=40)
phone = models.CharField(max_length=20)
class Appointment(models.Model):
appointment_time = models.DateTimeField()
unit = models.ForeignKey(Unit, on_delete=models.CASCADE)
staff = models.ForeignKey(Staff, on_delete=models.CASCADE)
prospect = models.ForeignKey(Prospect, on_delete=models.CASCADE)
status = models.BooleanField(default=False)
class Staff(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
manager = models.ManyToManyField(Manager, through=Manager.staff.through, related_name='+', blank=True)
unit = models.ManyToManyField(Unit, through=Unit.staff.through, related_name='+', blank=True)
profile_pic = models.ImageField(upload_to='profile_pic', blank=True)
class Manager(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
staff = models.ManyToManyField('Staff', related_name='+', blank=True)
company = models.CharField(max_length=40)
logo = models.ImageField(upload_to='logo_image', blank=True)
Upvotes: 2
Views: 850
Reputation: 477190
I think you make it too complex, you can use double underscores (__
) to follow a relation, Django also conceptually has bidirectional relations, so you also query ForeignKey
s, etc. in "reverse":
Prospect.objects.filter(appointment__staff__manager_user_id=2)
You can use .distinct()
[Django-doc] to retrieve unique Prospect
s:
Prospect.objects.filter(appointment__staff__manager_user_id=2).distinct()
The reason your query does not work is because your Appointment.objects.filter(..)
query is a collection of Appointment
s, you can query with:
Prospect.objects.filter(
appointment__in=Appointment.objects.filter(
staff__manager=Manager.objects.get(user=2)
)
)
But regardless, this will increase the number of queries with one, and is thus less efficient.
Upvotes: 2
Reputation: 755
Your issue is that appointment=x
, x must be 1 appointment. (if you want it to check against multiple, you can use appointment__in=x
.
So you can change it to:
appointment = Appointment.objects.filter(staff__manager=Manager.objects.get(user=2))[0] # see [0]
Prospect.objects.filter(appointment=appointment)
see this possible duplicate post: The QuerySet value for an exact lookup must be limited to one result using slicing. Filter error
Upvotes: 1