Adding support for importing models through the app registry while it is loading

2016-09-04 Thread Aymeric Augustin
Hello,

Since Django 1.7, `get_user_model()` cannot be called at import time. Django 
contains a lot of methods that start with `UserModel = get_user_model()` while 
it would be more natural to declare it as a global variable in the module. This 
trips up users and the reason why it’s forbidden isn’t obvious.


It's the consequence of two design decisions (which I’m responsible for) in the 
app-loading refactor.

1. Before Django 1.7, the sequence in which models were loaded could depend on 
which views were hit in what order after a WSGI process started. That allowed 
interesting failures mode. For example, a project could randomly fail to load, 
only in production, because of a circular import error. Throw multithreading 
into the mix and it could get really exciting. To solve this, the new 
app-loading system added an explicit `django.setup()` step that imports apps 
and models in a deterministic order and doesn’t let code interact with the app 
registry until it’s fully loaded.

2. Django must ensure that relationships between models are set up correctly. 
Specifically it must guarantee that reverse accessors are added to each model 
targeted by a foreign key. This guarantee can only be provided once all other 
models have been imported. There’s been a long string of bugs in this area 
around 2008 (if memory serves). The new app-loading system took this 
requirement into account at the design stage and, thanks to the explicit setup, 
is structurally more robust against such bugs.

Because of 2. apps.get_models() raises an exception before all models are 
imported rather than return an incomplete model. Because of 1. Django gives 
very little control on what happens up to this point.


However, in many cases, it doesn’t matter whether the model is fully 
constructed or not. In the use case I described in my introduction, the code 
only needs a reference to the model class at import time; that reference won’t 
be used until run time, after the app-loading process has completed. 
(Performing SQL queries through the ORM at import time doesn’t work anyway.)

For this reason, I think it would make sense to add an API similar to 
`apps.get_models()`, but that would work while app-loading is still in 
progress. It would make no guarantees about the functionality of the class it 
returns until app-loading has completed.

I implemented a proof of concept here: 
https://github.com/django/django/pull/6547.


I would appreciate feedback on the following questions:

1. Have you been missing this feature? If it’s needed outside of Django, I must 
make it a public API.

2. Is it reasonable to expose it as a public API? There’s a risk that 
StackOverflow will consider it as superior to get_models() because it’s more 
lax; they'll assume that I put checks in get_models() simply because I like 
messing with users.

3. Would you prefer adding a kwarg to get_models e.g. 
apps.get_models(settings.AUTH_USER_MODEL, unsafe=True) or adding a new method 
like the PR currently does? I’m thinking the former is more user friendly as 
the functionality is very similar.


Thanks,

-- 
Aymeric.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/67450ED7-88CD-49CE-9B63-180EDC033D55%40polytechnique.org.
For more options, visit https://groups.google.com/d/optout.


Re: Exceptions caught by the "include" template tag make it hard to rely on tests

2016-09-04 Thread Jon Dufresne
> Has anyone relied on the exception silencing behavior as a "feature" when
using {% include %}?

Not here.

+1 on deprecating the silencing behavior.

I have created a ticket [0] and PR [1] so others may get a sense of the
bigger picture change and how it could affect Django. Feedback welcome.

More generally, I find the template engine's behavior of replacing
exceptions with an empty string to cause more bugs than it prevents. In my
experience, loud errors will more likely be caught during development, unit
tests, and manual testing.

[0] https://code.djangoproject.com/ticket/27175
[1] https://github.com/django/django/pull/7208

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CADhq2b7%3Daxpcduaas68ihWugLhiffTPmAx0bQoyTy%3Dsa8Sq7GA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.