简体   繁体   中英

Significant performance issue with Django Admin - foreign key labels

I'm experience significant performance issue with Django Admin.

I have a mapping model where I map primary keys of 2 other modes

In my FundManagerMappingAdmin I try to represent the foreign key of the 2 tables with a label from the foreign key models.

The underlying models are about 4000 lines

I'm experiencing slow performance when retrieving the list in admin and then also when editing and updating

Could someone please point out the inefficiencies in this code?

Is there a better way please?

Admin.py

@admin.register(ChampDwDimFundManagerMapping)
class FundManagerMappingAdmin(admin.ModelAdmin):

list_display = ['get_champ_fund_manager_id', 'get_evestment_name', 'get_sharepoint_name', ]

def get_champ_fund_manager_id(self, obj):
    return obj.fund_manager_id
get_champ_fund_manager_id.short_description = 'CHAMP Manager ID'

def get_evestment_name(self, obj):
    return obj.evestment_fund_manager_id.manager_name
get_evestment_name.short_description = 'Evestment Manager Name'

def get_sharepoint_name(self, obj):
    return obj.sharepoint_fund_manager_id.manager_name
get_sharepoint_name.short_description = 'Sharepoint Manager Name'

def get_form(self, request, obj=None, **kwargs):
    form = super(ChampFundManagerMappingAdmin, self).get_form(request, obj, **kwargs)
    form.base_fields['sharepoint_fund_manager_id'].label_from_instance = lambda obj: "{} {}".format(obj.final_publications_fund_manager_id, obj.manager_name)
    form.base_fields['evestment_fund_manager_id'].label_from_instance = lambda obj: "{} {}".format(obj.evestment_fundmanager_id_bk, obj.manager_name)
    return form

Models.py

class FundManagerMapping(models.Model):
    fund_manager_id = models.AutoField(db_column='FundManagerId', primary_key=True)  
    sharepoint_fund_manager_id = models.ForeignKey(SharePointFundManager, models.DO_NOTHING, db_column='SharePointFundManagerId')  
    evestment_fund_manager_id = models.ForeignKey(EvestmentFundManager, models.DO_NOTHING, db_column='eVestmentFundManagerId')  

class EvestmentFundManager(models.Model):
    evestment_fund_manager_id = models.AutoField(db_column='eVestmentFundManagerId', primary_key=True)  
    package_execution_id = models.IntegerField(db_column='PackageExecutionId')  
    evestment_fund_manager_id_bk = models.CharField(db_column='eVestmentFundManagerId_BK', max_length=50)  
    manager_name = models.CharField(db_column='ManagerName', max_length=255)  

class SharePointFundManager(models.Model):
    sharepoint_fund_manager_id = models.AutoField(db_column='SharePointFundManagerId', primary_key=True)  
    package_execution_id = models.IntegerField(db_column='PackageExecutionId')  
    research_fund_manager_id = models.CharField(db_column='ResearchFundManagerId', max_length=50, blank=True, null=True)  
    final_publications_fund_manager_id = models.CharField(db_column='FinalPublicationsFundManagerId', max_length=50, blank=True, null=True)  
    manager_name = models.CharField(db_column='ManagerName', max_length=255)  

You are showing the name of related entities (because of get_evestment_name and get_sharepoint_name ) without joining/prefetching them. That means for every row that you display and every name of the related entity it requires django to make a database query. You need to override get_queryset() of the ModelAdmin and use select_related to tell django to join those entities from the beginning so that it does not need any additional queries to get those names:

@admin.register(ChampDwDimFundManagerMapping)
class FundManagerMappingAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        return super().get_queryset(request).select_related(
            'sharepoint_fund_manager_id', 
            'evestment_fund_manager_id',
        )

Also you don't name ForeignKey fields something_id . It is just sharepoint_fund_manager because what you get when you call fund_manager.sharepoint_fund_manager_id is not an id but an instance of SharePointFundManager . It is weird to call sharepoint_fund_manager_id.name . An id does not have a name attribute. A fund manager has.

Additionally Django does automatically create a property sharepoint_fund_manager_id for you if you call the field sharepoint_fund_manager to access the plain foreign key.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM