2

I'm making a classic single view application, mapping multiple datasources.

Django-admin is paginated so there's no impact when I view my list, the problem is when I want to change/add it is .

Using the debug-toolbar my queries look fine, I don't think they take a long time.

I tried to use a suggestion here Django admin change form load quite slow and created a form, but this had no impact.

When is use exclude = ['e_vehicle','e_product'] it's no surprise that add/change screens load instantly.

Any thoughts please

enter image description here

model.py

class Product_Mapping(Trackable):
    product_mapping_id = models.AutoField(primary_key=True)   
    s_product =  models.OneToOneField(sProduct, on_delete=models.CASCADE)
    e_fund_manager = models.ForeignKey(eManager, models.DO_NOTHING, blank=True, null=True)
    e_product = models.ForeignKey(eProduct, models.DO_NOTHING, blank=True, null=True)
    e_vehicle = models.ForeignKey(eVehicle, models.DO_NOTHING, blank=True, null=True)

eManager has around 3K

eProduct has around 17K (has fkey to eManager)

eVehicle has around 25K (has fkey to eProduct)

form.py

class MappingProductForm(forms.ModelForm):
    s_product = forms.ChoiceField(required=False,
                            choices=sProduct.objects.values_list('final_publications_product_id', 'product_name'))
    e_fund_manager = forms.ChoiceField(required=False,
                            choices=eManager.objects.values_list('e_fund_manager_id', 'manager_name'))
    e_product = forms.ChoiceField(required=False,
                            choices=eProduct.objects.values_list('e_product_id', 'product_name'))
    e_vehicle = forms.ChoiceField(required=False,
                            choices=eVehicle.objects.values_list('e_vehicle_id', 'formal_vehicle_name'))

    class Meta:
        model = Product_Mapping
        fields = '__all__'

admin.py

@admin.register(Product_Mapping)
class ChampProductMappingAdmin(admin.ModelAdmin): 
    form = MappingProductForm
Glenn Sampson
  • 1,188
  • 3
  • 12
  • 30
  • 2
    Did you try using [`raw_id_fields`](https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.raw_id_fields) for those 2 foreign keys? – Selcuk Apr 03 '19 at 01:33

1 Answers1

3

It can be seen that there are too many values in e_product and e_vehicle tables. You are using ChoiceField it means inside HTML dropdown there would be ~17K-25K options this would slow down rendering and sometimes hang on client side.

Solution

edit your forms.py


from django.contrib.admin.widgets import ForeignKeyRawIdWidget

class MappingProductForm(forms.ModelForm):


    def __init__(self, *args, **kwargs):
        super(MappingProductForm, self).__init__(*args, **kwargs)
        rel_model = self.Meta.model
        rel_eprod = rel_model._meta.get_field('e_product').rel
        rel_eprod = rel_model._meta.get_field('e_vehicle').rel
        self.fields['e_product'].widget = ForeignKeyRawIdWidget(rel_eprod, admin_site=admin.site)
        self.fields['e_vehicle'].widget = ForeignKeyRawIdWidget(rel_eprod, admin_site=admin.site)

    s_product = forms.ChoiceField(required=False,
                            choices=sProduct.objects.values_list('final_publications_product_id', 'product_name'))
    e_fund_manager = forms.ChoiceField(required=False,
                            choices=eManager.objects.values_list('e_fund_manager_id', 'manager_name'))
    e_product = forms.ModelChoiceField(required=False,
                            choices=eProduct.objects.all())
    e_vehicle = forms.ModelChoiceField(required=False,
                            choices=eVehicle.objects.all()
                            )

    class Meta:
        model = Product_Mapping
        fields = '__all__'

This would keep raw id as widget. You can get something like below.

enter image description here

You can add other entries by hitting search button besides input.

This is better option when you have lots of choices in ModelChoiceField

Devang Padhiyar
  • 3,427
  • 2
  • 22
  • 42
  • 1
    I know this is a separate question but related, is there a way to load a different form for add vs change? – Glenn Sampson Apr 03 '19 at 22:52
  • 1
    Yes It is possible! You may check `_changeform_view()` method and `add_view()` of `django.contrib.admin.options.ModelAdmin` class. Yet, this is not better place to write big answers :) – Devang Padhiyar Apr 04 '19 at 04:19