Hi Petros,

I think the raw_id_fields still display the __str__/__unicode__ of the 
selected object so therefore need to get queried. I wonder if 
select_related would possibly help?

Collin

On Wednesday, December 24, 2014 5:53:02 AM UTC-6, Ernest0x wrote:
>
> On 12/24/14 13:30, 'Petros Moisiadis' via Django users wrote: 
> > On 12/23/14 19:13, 'Petros Moisiadis' via Django users wrote: 
> >> Hello people :) 
> >> 
> >> I am struggling with optimizing an admin with inlines which causes too 
> >> many database requests. 
> >> 
> >> My model structure is like this: 
> >> 
> >>     class ExampleA(models.Model): 
> >>         ... 
> >>     
> >>     class ExampleB(models.Model): 
> >>         aexample = models.ForeignKey('ExampleA', 
> related_name='bexamples') 
> >>         cexample = models.ForeignKey('ExampleC') 
> >>         dexample = models.ForeignKey('ExampleD') 
> >>         eexample = models.ForeignKey('ExampleE') 
> >>         ... 
> >> 
> >>     class ExampleC(models.Model): 
> >>         ... 
> >>     
> >>     class ExampleD(models.Model): 
> >>         ... 
> >>     
> >>     class ExampleE(models.Model): 
> >>         ... 
> >> 
> >> The admin classes: 
> >> 
> >>     class ExampleBInline(admin.StackedInline): 
> >>         model = ExampleB 
> >>         extra = 0 
> >> 
> >>     class ExampleAAdmin(admin.ModelAdmin): 
> >>         inlines = [ExampleBInline] 
> >> 
> >>     admin.site.register(ExampleA, ExampleAAdmin) 
> >> 
> >> As I can see with django-debug-toolbar, when rendering the admin 
> >> template for the inline formset with the forms for ExampleB objects, a 
> >> new db request is sent to db server for each related field of each 
> >> ExampleB object. Particularly, I am seeing a lot of queries like these: 
> >> 
> >>     SELECT ••• FROM `examplec` WHERE `examplec`.`id` = 1 LIMIT 21 
> >>     SELECT ••• FROM `examplee` WHERE `examplee`.`id` = 2 LIMIT 21 
> >>     SELECT ••• FROM `examplec` WHERE `examplec`.`id` = 2 LIMIT 21 
> >>     SELECT ••• FROM `exampled` WHERE `exampled`.`id` = 2 LIMIT 21 
> >>     SELECT ••• FROM `examplee` WHERE `examplee`.`id` = 3 LIMIT 21 
> >> 
> >> The template context is this (I am using grappelli): 
> >>     
> >>                     21        {% if field.is_readonly %} 
> >>                     22            <div class="grp-readonly">{{ 
> >> field.contents|linebreaksbr }}</div> 
> >>                     23        {% else %} 
> >> the marked line =>  24            {{ field.field }} 
> >>                     25        {% endif %} 
> >>                     26    {% endif %} 
> >>                     27        {% if line.fields|length_is:'1' %}{{ 
> >> line.errors }}{% endif %} 
> >> 
> >> 
> >> I have tried the following optimizations: 
> >> 
> >> First try: 
> >> 
> >>     class ExampleAAdmin(admin.ModelAdmin): 
> >>         inlines = [ExampleBInline] 
> >> 
> >>         def get_queryset(self, request): 
> >>             qs = super(ExampleAAdmin, self).get_queryset(request) 
> >>             return qs.prefetch_related('bexamples', 
> >> 'bexamples__cexample', 'bexamples__dexample', 'bexamples__example') 
> >> 
> >> Second try: 
> >> 
> >>     class ExampleBInline(admin.StackedInline): 
> >>         model = ExampleB 
> >>         extra = 0 
> >>       
> >>         def get_queryset(self, request): 
> >>             qs = super(ExampleInline, self).get_queryset(request) 
> >>             return qs.select_related('cexample', 'dexample', 
> 'eexample') 
> >> 
> >> Third try: 
> >> 
> >>     class BaseExampleBFormSet(BaseInlineFormSet): 
> >>         def __init__(self, *args, **kwargs): 
> >>             super(BaseExampleBFormSet, self).__init__(*args, **kwargs) 
> >>             qs = self.queryset 
> >>             self.queryset = qs.select_related('cexample', 'dexample', 
> >> 'eexample') 
> >> 
> >>     ExampleBFormSet = inlineformset_factory(ExampleA, ExampleB, 
> >> formset=BaseExampleBFormSet) 
> >> 
> >>     class ExampleBInline(admin.StackedInline): 
> >>         model = ExampleB 
> >>         extra = 0 
> >>         formset = ExampleBFormSet 
> >> 
> >> Unfortunately, none of the above works. 
> >> 
> >> So, I would be really grateful if anyone could help on this by giving 
> >> any hint or pointing out what could be possibly missing. Or, could I 
> >> have hit a restriction of django admin's internals? 
> >> 
> >> Thank you in advance, 
> >> 
> >> Petros 
> >> 
> > Hello again, 
> > 
> > I would like to clarify that the big number of db requests is not caused 
> > by fetching all the objects for the related model to populace select 
> > boxes for the related fields in the line, as it is often the case. To 
> > avoid that, I have included the related fields in raw_id_fields. I have 
> > also used grappelli's convenient autocomplete lookup feature, but that 
> > does not add extra queries. So, the inline class actually looks like 
> this: 
> > 
> >     class ExampleBInline(admin.StackedInline): 
> >         model = ExampleB 
> >         extra = 0 
> >         raw_id_fields = ['cexample', 'dexample', 'eexample'] 
> >         autocomplete_lookup_fields = { 
> >             'fk': ['cexample', 'dexample', 'example'], 
> >             } 
> > 
> > The only optimization that works is adding the related fields in 
> > readonly_fields in combination with a queryset changing method with 
> > select_related(), like this: 
> > 
> >     class ExampleBInline(admin.StackedInline): 
> >         model = ExampleB 
> >         extra = 0 
> >         raw_id_fields = ['cexample', 'dexample', 'eexample'] 
> >         autocomplete_lookup_fields = { 
> >             'fk': ['cexample', 'dexample', 'eexample'], 
> >             } 
> >         readonly_fields = ['cexample', 'dexample', 'eexample'] 
> > 
> >         def get_queryset(self, request): 
> >             qs = super(ExampleBInline, self).get_queryset(request) 
> >             return qs.select_related('cexample', 'dexample', 'eexample') 
> > 
> > 
> > However, I am not satisfied with that solution because I do want to be 
> > able to edit the related fields inline. 
> > 
>
> So the question merely is why the inline class right above produces so 
> many queries if the 'readonly_fields' line is commented out? 
> For my data, according to debug toolbar, the view causes 11 queries with 
> readonly_fields and 115 queries without readonly_fields. 
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/778f1f33-3c34-491e-a062-9527ec703bfd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to