Hello Collin,
On 12/29/14 07:25, Collin Anderson wrote:
> 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?
>
I do have select_related in the queryset (look at the last version of
ExampleBInline in my previous post).
The thing is that if the same fields that are included in raw_id_fields
are also included in readonly_fields, the queries are reduced
dramatically, despite the fact that the same amount of information is
displayed in both cases. __str__()/__unicode__ is still called when the
fields are in readonly_fields, so it is really very strange why there is
difference between adding and commenting out the readonly_fields line.
Very strange...
> 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]
> <mailto:[email protected]>.
> To post to this group, send email to [email protected]
> <mailto:[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
> <https://groups.google.com/d/msgid/django-users/778f1f33-3c34-491e-a062-9527ec703bfd%40googlegroups.com?utm_medium=email&utm_source=footer>.
> For more options, visit https://groups.google.com/d/optout.
--
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/54A1A0FB.8030508%40yahoo.gr.
For more options, visit https://groups.google.com/d/optout.