简体   繁体   中英

Django - Query extended models effeciently

I have a BaseModel(models.Model), and ExtendedModelA(BaseModel) and ExtendedModelB(BaseModel). ExtendedModelA and ExtendedModelB both have foreign key fields to other models. Their unicode methods return a field from this foreign key related model.

I have a dropdown menu which I want to populate with BaseModel objects (which naturally includes ExtendedModelA and ExtendedModelB objects). To do this I need a queryset which will get all extended objects (type A and B) and their related objects.

I have a merged queryset:

queryset = BaseModel.objects.filter(type=1).select_related('extendedmodela') | BaseModel.objects.filter(type=2).select_related('extendedmodelb')

The trouble is that the unicode representation of the BaseModel is presented in the dropdown. If I add a unicode method to the BaseModel class which has conditions:

    if hasattr(self, extendedmodela):
        return self.extendedmodela.__unicode__()
    else:
        return self.extendedmodelb.__unicode__()

This results in querying the database for each object.

Anyone any ideas about how to get myself out of this mess?

Essentially I need to formulate a queryset which will get all BaseModel objects efficiently, and when they're displaying in the dropdown their unicode methods for their respective extended classes (which print fields from a foreign key field object) dont hammer the database. I have a few thousand objects so the database takes a hit.

Cheers,

Dean

You're using select_related , which is good. I think you can optimize your query by using a Q , which essentially lets you filter for either type 1 or type 2 in this case.

from django.db.models import Q

BaseModel.objects.filter(Q(type=1) | Q(type=2)).select_related('extendedmodela').select_related('extendedmodelb')

EDIT

You can use the double-underscore notation to access deeper fields that are on related models. eg.

 .select_related('extendedmodela', 'extendedmodela__fkfieldname')

Why not just pass a mixed bag to the dropdown. This is no longer a QuerySet , but the dropdown won't mind:

qs = list(ExtendedModelA.objects.select_related('whatever_fk_needed')) +\
     list(ExtendedModelB.objects.select_related('whatever_fk_needed'))

Whatever instance is selected, will have the same id as its BaseModel instance.

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