Slow test startup under Django 1.7

2015-01-22 Thread Warren Smith
I'm in the process of converting a large legacy app from Django 1.5 to 1.7. 
I've got all the tests passing, so I'm researching an issue I noticed 
during the course of my work: Test startup takes MUCH longer under Django 
1.7 than it did under 1.5. I've got a test that, when run by itself, took a 
total of 5 seconds under 1.5. Under 1.7 it takes over a minute.

To isolate the test startup, I setup a do-nothing test method within a 
subclass of django.test.TestCase. I ran it under Django 1.5 and 1.7 with 
similar results to the existing "real" test.

I ran the do-nothing test within cProfile under Django 1.7 and found 
something very interesting. According to pstats, the method 
django.apps.config.AppConfig.get_models() was called 2.2+ MILLION times. 
Even with 79 django apps in my INSTALLED_APPS setting, that seems excessive.

I read the Django 1.7 release notes, especially the App Config stuff. I 
noticed the warning about not importing models in the application root 
module. I went through all of our internal apps and made sure they were not 
importing models in the root module. I had to make some changes, moving 
imports inside functions/methods. I also looked at my third-party 
dependency apps. None of those were importing their models in their root 
modules.

After all that, though, I still see no change in behavior.

I thought I might have some loop happening somewhere, though why it wasn't 
infinite was interesting. It would be nice to know more about the context 
of those get_models() calls. Perhaps I had a couple of mis-behaving apps 
locked in a deadly embrace of some sort.

I hacked on my locally installed django.apps.config.AppConfig class, adding 
a class-level collections.Counter that gets incremented for self.label by 
the get_models() method.
I dumped the results to a json file within my do-nothing test. It wouldn't 
be comprehensive, but at least it would show me what had happened before 
the test ran.

I expected to see a few big numbers and a lot of small ones. As often 
happens when profiling, my expectations were completely wrong. All the 
counts were very similar, all in the 6000-7999 range. All 79 of my apps 
were represented.

Is there some sort of cartesian product going on here?

Is this behavior normal and expected?

-- 
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 django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
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/4c698390-e8e2-437e-ae74-34c796986275%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Django Templates: Using the "with" statement and "block.super" together

2013-09-24 Thread Warren Smith
On occasion, I've used the following technique in my django templates:

# parent.html 

{% block someblock %}
…stuff…
  {% if cool_optional_feature_is_enabled %}
…optional stuff...
  {% endif %}
…stuff...
{% endblock %}


# child.html
{% extends "parent.html" %}

{% block someblock %}
  {% with True as cool_optional_feature_is_enabled %}
{{ block.super }}
  {% endwith %}
{% endblock %}


The cool thing is that this technique allows a child template to 
essentially enable a feature in the parent template. The same technique can 
also be used to disable a feature in the parent template, or really 
anything that can be driven from a context variable, since, as I understand 
it, that is what the with statement is doing: temporarily injecting a 
variable into the context within which the expressions in a chunk of 
template code are evaluated against.

I was showing this to a colleague today and, though he thought it was neat, 
he had never seen it before and was concerned that it was not a mainstream 
use of the django template language. I did some cursory google searches and 
couldn't find any overt references to this ability either.

My concern is that I may be relying on some undocumented side-effect of the 
way that blocks or the with statement are implemented and that, at some 
point in the future, this will be changed and all of my templates that use 
this will break.
 

-- 
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 django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
For more options, visit https://groups.google.com/groups/opt_out.