Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ModelAdmin get_object optimization

I've optimized get_queryset in Django ModelAdmin list view with:

  • .only('field1', 'field2',)
  • .select_related('rel1',)

These optimizations are not the same that I need for get_object change view :

  • .only('field1', 'field2', 'field3',)
  • .select_related('rel1__rel2', 'rel3',)
  • .prefetch_related(...)

Thing is, get_queryset and get_object are coupled:

class BaseModelAdmin(...):

  ...

  def get_object(self, request, object_id, from_field=None):
      """
      Returns an instance matching the field and value provided, the primary
      key is used if no field is provided. Returns ``None`` if no match is
      found or the object_id fails validation.
      """
      queryset = self.get_queryset(request)
      model = queryset.model
      field = model._meta.pk if from_field is None else model._meta.get_field(from_field)
      try:
          object_id = field.to_python(object_id)
          return queryset.get(**{field.name: object_id})
      except (model.DoesNotExist, ValidationError, ValueError):
          return None

How can I override get_queryset without having to copy/paste all the boiler plate above?

like image 576
Benjamin Toueg Avatar asked Apr 16 '26 01:04

Benjamin Toueg


1 Answers

I've come up with this solution, which seems a good compromise:

def get_queryset(self, request):
    queryset = super().get_queryset(request)
    if request.resolver_match.url_name.endswith('_change'):
        # admin change view
        queryset = queryset.only(
            'iso_code',
            *get_translation_fields('name'),
            'official_languages',
            'active',
            'currency_code',
            'currency_symbol',
        )
    else:
        # admin change list
        queryset = queryset.only(
            'iso_code',
            'name',
            'active',
        )
    return queryset
like image 87
Benjamin Toueg Avatar answered Apr 19 '26 14:04

Benjamin Toueg