Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#30455 closed Cleanup/optimization (invalid)

Django ModelForm with multiple ForeignKey query optimisation issue.

Reported by: Bishnu Bhattarai Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In django ModelForm, I have two foreignkey fields 'account' and reference,

self.fieldsaccount.queryset = Account.objects.all()
self.fieldsreference.queryset = Billing.objects.all()

I have 2000 rows in Account table and 4000 rows in Billing table.
While rendering this form, server responded with 504 status.

I thought, while rendering this form, these two queryset are executed at once and sets the options in choice filed. But I found the queryset are executed in loop and response server error 504. This is because database is hit for every choices of foreignkey and db-query is executed in loop.

Hoping the issue will be resolved soon.

Change History (7)

comment:1 by Mariusz Felisiak, 5 years ago

Component: FormsDatabase layer (models, ORM)
Resolution: invalid
Status: newclosed
Version: 2.1master

You can use select_related() to prevent multiple queries.

Closing per TicketClosingReasons/UseSupportChannels.

comment:2 by Bishnu Bhattarai, 5 years ago

Resolution: invalid
Status: closednew

We cannot use select_related for two unrelated querysets in django form. Can you please give me some example. The solution you have provided is not what I mean. Please test django-model form with two foreignkey fields in forms and with rows that I have mentioned above it will not response as fast as we need takes more than 40-50 sec and gets timeout.

comment:3 by Mariusz Felisiak, 5 years ago

Sorry I missed that you're talking about ModelForm. If you have form with two fields (e.g. ModelChoiceField) then queryset for each field will be executed once, I don't understand what loop do you mean. Can you provide example project?

comment:4 by Bishnu Bhattarai, 5 years ago

class BillingForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(BillingForm, self).__init__(*args, **kwargs)
       self.fields['account'].queryset = Account.objects.all()
       self.fields['refrence'].queryset = Billing.objects.all()

    class Meta:
        model   = Billing
        fields  = ('account', 'refrence',  'amount', 'remarks', )
    
    views.py

    class BillingUpdateView(SuccessMessageMixin, UpdateView):
    template_name   = 'billing/billing-form.html'
    model           = Billing
    form_class      = BillingForm
    success_url     = reverse_lazy('billing_report')
    success_message = 'Billing Updated Successfully.'

    @method_decorator(staff_required())
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

I have 2000 rows in Account table and 4-5K rows in Billing table. Try to render the above example form with number of rows that I have mentioned and see the response time. You can use model_mummy for generate dummy data.

Last edited 5 years ago by Mariusz Felisiak (previous) (diff)

comment:5 by Mariusz Felisiak, 5 years ago

Resolution: invalid
Status: newclosed

I don't see any issue here you have two querysets so two queries, nothing unusual. Maybe your Account, Billing models are complicated, it's hard to tell without an entire project. It is normal that if you want to render a long list it will take time, I'm not sure what do you expect from Django and where we could be smarter 🤷.

Please use one of support channels.

comment:6 by Bishnu Bhattarai, 5 years ago

Please have a look at this issue, Have you tried with my views and number of rows. If just 5 thousands rows in a table responding 504 status or taking more than one minute, then how it is useful ? Please immitate my situation with number of rows in mysql db, you will certainly get noticed what's wrong. I have got noticed this issue after debugging it for two days.

comment:7 by Mariusz Felisiak, 5 years ago

5000 rows in each of foreign keys works perfectly for me, ~1sec. for render. Trac is not a place for debugging code. Again, please use one of support channels, I'm sure that you will find help on e.g. #django IRC channel.

Note: See TracTickets for help on using tickets.
Back to Top