Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Queryset takes too long to populate data

I have a django view that generates a form depending on POST or GET. It works well with little data on the Student model but stagnates when the data gets big. Is there a remedy I can apply??
Here’s the view

def My_View(request,pk):
    if request.method == 'POST':
        try:
            form = NewIssueForm(request.POST,school= request.user.school,pk=pk,issuer = request.user)
            if form.is_valid():
                name = form.cleaned_data['borrower_id'].id
                form.save(commit=True)
                books = Books.objects.get(id=pk)
          
                Books.Claimbook(books)
                return redirect('view_books')
                messages.success(request,f'Issued successfully')
        except Exception as e:
            messages.warning(request,f"{e}")
            return redirect('view_books')    
    else:
        form = NewIssueForm(school= request.user.school,pk=pk,issuer = request.user)
    return render(request, 'new_issue.html', {'form': form})

Here’s the form

class NewIssueForm(forms.ModelForm):
    def __init__(self,*args, pk,school,issuer, **kwargs):
        super(NewIssueForm, self).__init__(*args, **kwargs)
        booqs = Books.objects.filter(school=school).get(id=pk)
        self.fields['issuer'].initial = issuer
        self.fields['borrower_id'].Student.objects.filter(school = school)
        self.fields['book_id'].label = str(booqs.book_name) + " - " + str(booqs.reg_no)
        self.fields['book_id'].initial = pk
  
    class Meta:
        model = Issue
        fields = ['issuer','book_id','borrower_id','due_days']
        widgets = {
            'book_id':forms.TextInput(attrs={"class":'form-control','type':''}),
            'issuer':forms.TextInput(attrs={"class":'form-control','type':'hidden'}),
            'borrower_id': Select2Widget(attrs={'data-placeholder': 'Select Student','style':'width:100%','class':'form-control'}),
            'due_days':forms.TextInput(attrs={"class":"form-control"}),

Student model

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class Student(models.Model):                                    
    school = models.ForeignKey(School, on_delete=models.CASCADE)
    name = models.CharField(max_length=200,help_text="The student's name in full")
    now = datetime.datetime.now()
    YEAR = [(str(a), str(a)) for a in range(now.year-5, now.year+1)]
    year = models.CharField(max_length=4, choices = YEAR,help_text='The year the student is admitted in school')
    student_id = models.CharField(max_length=40,help_text = "This is the student's admission number")
    klass = models.ForeignKey(Klass,on_delete=models.CASCADE)
    stream = models.ForeignKey(Stream,on_delete=models.CASCADE)
    graduated = models.BooleanField(default=False,help_text = "Tick the box to mark the student as graduated")
    prefect = models.BooleanField(default=False,help_text = "Tick the box to select the student as a prefect")

    def __str__(self):
        return "%s - %s - F%s %s"%(self.student_id,self.name,self.klass,self.stream)
    class Meta:
        verbose_name_plural = 'Students'
        unique_together = ("school", "student_id",)
        indexes = [models.Index(fields=['student_id']),
                   models.Index(fields=['name', ]),

>Solution :

The reason this happens is because when you render the Student, it will need to fetch the related Klass and Stream objects, and will make a query per Student object. This problem is called an N+1 problem since fetching n student requires one query to fetch all the Students, and then one query per Student for the Klasses, and one query per Student for the Streams.

You can select the data when you select the students with:

self.fields['borrower_id'].Student.objects.filter(
    school=school
).select_related('klass', 'stream')

Depending on the __str__ implementations of other models, you might have to select data along with these models as well.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading