0

I'm running into the fairly common issue that the django admin inline does a whole bunch of unnecessary queries to populate the dropdown. There are 4 models - when I view the user, I would like to see UserClientRoles associated with that user, displayed with the ClientRole name and the Client. When I just use the role name, it queries once for each UserClientRole (if there 3 assignments, it queries 3 times). If I include the client name, it queries every client name once for every UserClientRole.

I've tried the solution outlined here (Django admin inline: select_related), but no dice. It doesn't modify the behavior. I've also tried overriding the get_queryset method on the UserAdmin class to no effect. Nothing I've tried reduces the number of queries. I've deleted some model details for conciseness.

Here's the models:

class User(models.Model):
    id = models.AutoField(primary_key=True)
    email = models.CharField(unique=True, max_length=200)


class Client(models.Model):
    id = models.AutoField(primary_key=True)
    client_name = models.CharField(unique=True, max_length=200)
    client_identifier = models.CharField(unique=True, max_length=200)


class ClientRole(models.Model):
    client_role_id = models.AutoField(primary_key=True)
    role_name = models.CharField(unique=True, max_length=200)
    client = models.ForeignKey(Client)

    def __unicode__(self):
        return self.role_name + self.client_id.client_name


class UserClientRole(models.Model):
    user_client_role_id = models.AutoField(primary_key=True)
    client_role = models.ForeignKey(ClientRole)
    user = models.ForeignKey(User)

And here are the admin models:

class UserClientRoleFormset(forms.BaseInlineFormSet):
    def __init__(self, *args, **kwargs):
        super(UserClientRoleFormset, self).__init__(*args, **kwargs)
        self.queryset = self.queryset.prefetch_related("client_role__client")


class UserClientRoleInline(admin.TabularInline):
    model = UserClientRole
    extra = 1
    formset = UserClientRoleFormset


@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    inlines = (UserClientRoleInline,)

Any clue what I'm missing?

Community
  • 1
  • 1
canisrufus
  • 665
  • 2
  • 6
  • 19
  • did you try my answer? – e4c5 Dec 19 '16 at 16:09
  • @e4c5 i didn't design the table structure and am not in the position to rewrite it. i also feel like there's some information loss between the structure i have and the structure you have, so it wasn't clear to me that it was a step forward – canisrufus Dec 19 '16 at 18:39
  • Far from it, there isn't any information loss there at all. Your existing structure doesn't even make use of the built in django Many to many relation – e4c5 Dec 19 '16 at 22:42
  • @e4c5 hey did you delete your answer? this problem didn't have my full attention, and i think i can see how your suggestions might help now. wish you'd restore it so we could give it a try. – canisrufus Jan 03 '17 at 17:04
  • hi, sorry I thought the question was abandoned :-) – e4c5 Jan 03 '17 at 17:19
  • undeleted just now – e4c5 Jan 03 '17 at 17:20
  • @e4c5 nah just got a lot of other stuff on my plate. gonna get to it... – canisrufus Jan 13 '17 at 10:41
  • 1
    It's really bad form to ask questions and expect people to spend time to answer them if you are not going to spend time to look into those answers – e4c5 Jan 13 '17 at 10:42
  • @e4c5 This really hits a nerve dude. Consider the possibility that you're making ungenerous assumptions about what's happening here. I've been taking time off work to deal with my dad's dementia + malignant growth. I'm managing a ~7 person group, and i was doing this to help a junior developer because they weren't equipped to figure it out. I spent 5 hours on it and had to move on. It's a problem that needs solving, but there are 40 other problems that need solving, and this hasn't reached the top of the stack. I appreciate your input, and I'm gonna get to it. – canisrufus Jan 13 '17 at 10:53
  • Deepest sympathies about your father's illness. And I wish him a speedy recovery. And I also stand by what I said. – e4c5 Jan 13 '17 at 10:54

1 Answers1

2

Try:

self.queryset.select_related('client_role', 'client_role__client')

Django isn’t always the best at making decisions about which objects to select as part of the query and even though you might think the django ORM is smart enough to recognize that since you are traversing a relation ship of the form related_parent__related_child, it isn’t. So making sure to specify both in the select_related or prefetch_related has worked for me in the past. I would recommend trying it out!

2ps
  • 15,099
  • 2
  • 27
  • 47