Llanilek
Llanilek

Reputation: 3466

Optimising django queries to avoid duplicates when using detail view and overriding get_context_data

I'm trying to reduce the number of duplicated queries when using CBVs such as DetailView and then overriding get_context_data to filter a model based on related models.

Right now, I have a DetailView for a PatientCase model and want to create two variables in the context for a related model CasePhotos the relationship is via a foreign key on the CasePhoto model.

class CasePhoto(models.Model):
    ...
    patient_case = models.ForeignKey(PatientCase, on_delete=models.CASCADE)
    photo = models.URLField()
    is_mentor_edit = models.BooleanField(default=False)
    ...

Now, I know this is bad, but I cannot seem to find the correct optimal way to do this. Some guidance and even better some documentation links that I've obviously overlooked somewhere would be even better.

class ReviewCaseView(DetailView):
    model = PatientCase

def get_context_data(self, **kwargs):
    patient_case = self.get_object()
    context = super().get_context_data(**kwargs)
    case_photos = CasePhoto.objects.filter(patient_case=patient_case)
    context['case_photos'] = case_photos.filter(is_mentor_edit=False)
    context['mentor_photos'] = case_photos.filter(is_mentor_edit=True)
    return context

I know that the duplication is line 5 patient_case = self.get_object() as detail.py calls get_object which is what creates the first query. Is there a way of caching this to reuse in get_context_data or maybe a better way without get_context_data at all?

Upvotes: 2

Views: 306

Answers (1)

Alasdair
Alasdair

Reputation: 309039

In DetailView, the get() method sets self.object = get_object() before calling get_context_data, therefore you don't have to call get_object() again.

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    patient_case = self.object
    case_photos = CasePhoto.objects.filter(patient_case=patient_case)
    context['case_photos'] = case_photos.filter(is_mentor_edit=False)
    context['mentor_photos'] = case_photos.filter(is_mentor_edit=True)
    return context

Upvotes: 2

Related Questions