查询集填充数据的时间太长

Queryset takes too long to populate data

我有一个 Django 视图,它根据 POST 或 GET 生成一个表单。它在 Student 模型上适用于少量数据,但在数据变大时停滞不前。有没有我可以申请的补救措施? 这是 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})

这是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"}),

学生模型

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', ]),

猜不出你的型号,但看起来 select_related 可能会耍花招。

发生这种情况的原因是因为当您渲染 Student 时,它需要获取 相关的 KlassStream 对象,并将查询 per Student 对象。这个问题被称为 N+1 问题 因为获取 n 学生需要一个查询来获取所有 Student,然后一个每个 Student 个查询 Klass 个,每个 Student 个查询 Stream 个。

当您 select 学生具有以下条件时,您可以 select 数据:

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

根据其他模型的 __str__ 实现,您可能还需要 select 数据以及这些模型。