Using auth stuff without installing the auth app

589 views
Skip to first unread message

Matt

unread,
Mar 22, 2016, 8:57:41 PM3/22/16
to Django developers (Contributions to Django itself)
I like to use the authentication machinery in Django, without explicitly putting 'django.contrib.auth' in INSTALLED_APPS. This prevents a bunch of unused tables from being creating in the database.

This was possible in earlier version of Django. In 1.8, a spurious warning was generated, but that was fixed in #24564 (https://groups.google.com/forum/#!searchin/django-developers/$2324564/django-developers/7b4xzkjLFH8/wLJ83Bxa_h4J)

In Django 1.9, it doesn't seem possible anymore (see traceback). Using the auth stuff without installing the app -- is that something we want to support or not?

Traceback (most recent call last):
  File "/usr/lib/python3.4/wsgiref/handlers.py", line 137, in run
    self.result = application(self.environ, self.start_response)
    return self.application(environ, start_response)
    self.load_middleware()
    mw_class = import_string(middleware_path)
    module = import_module(module_path)
  File "/usr/lib/python3.4/importlib/__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 2231, in _gcd_import
  File "<frozen importlib._bootstrap>", line 2214, in _find_and_load
  File "<frozen importlib._bootstrap>", line 2203, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1129, in _exec
  File "<frozen importlib._bootstrap>", line 1448, in exec_module
  File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
    from django.contrib.auth.backends import RemoteUserBackend
    from django.contrib.auth.models import Permission
    class Permission(models.Model):
    "INSTALLED_APPS." % (module, name)
RuntimeError: Model class django.contrib.auth.models.Permission doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.

Florian Apolloner

unread,
Mar 23, 2016, 4:49:32 AM3/23/16
to Django developers (Contributions to Django itself)
Oh yes, this is a bug. We should ensure that RemoteUser backend is imported in the middleware itself or that backends.py does not trigger any model imports. Since the usage of any of the backends requires models, the import there seems fine -- I'd import RemoteUserBackend in RemoteUserMiddleware.__init__ -- A patch would be very welcome.

Cheers,
Florian

Matt

unread,
Mar 23, 2016, 3:36:39 PM3/23/16
to Django developers (Contributions to Django itself)


> Since the usage of any of the backends requires models

I used the ModelBackend with no issues in Django 1.8 (without auth in INSTALLED_APPS). So that is the place I want to refactor.


I'm trying to write a regression test for this, but I can't think of a good way to do it. Essentially, I want to ensure django.contrib.auth.context_processors/middleware/backends can be imported if django.contrib.auth is not in INSTALLED_APPS. Using `override_settings(INSTALLED_APPS...)` doesn't "undo" the imports, so importing the modules again won't trigger an exception. Any ideas?

Florian Apolloner

unread,
Mar 23, 2016, 6:39:57 PM3/23/16
to Django developers (Contributions to Django itself)


On Wednesday, March 23, 2016 at 8:36:39 PM UTC+1, Matt wrote:
I created https://code.djangoproject.com/ticket/26401

> Since the usage of any of the backends requires models

I used the ModelBackend with no issues in Django 1.8 (without auth in INSTALLED_APPS). So that is the place I want to refactor.

Mhm, that would surprise me -- the ModelBackend uses the Permission model, so why would that ever work without beeing in INSTALLED_APPS? And as for the ticket you generated, the context_processor will break due to the AnonymousUser most likely -- this is not backend related.

Matt

unread,
Mar 23, 2016, 7:07:14 PM3/23/16
to Django developers (Contributions to Django itself)
>  the ModelBackend uses the Permission model, so why would that ever work without beeing in INSTALLED_APPS?

ModelBackend.authenticate() doesn't use the permissions models. And that's the method that gets used when authenticating a user. If I did something like `user.has_perm()`, things would blow up. But that is easy to override on your custom User class.


> the context_processor will break due to the AnonymousUser most likely

Hmm, right...I suppose AnonymousUser could be refactored into base_user.py.

Florian Apolloner

unread,
Mar 23, 2016, 7:19:58 PM3/23/16
to Django developers (Contributions to Django itself)


On Thursday, March 24, 2016 at 12:07:14 AM UTC+1, Matt wrote:
>  the ModelBackend uses the Permission model, so why would that ever work without beeing in INSTALLED_APPS?

ModelBackend.authenticate() doesn't use the permissions models. And that's the method that gets used when authenticating a user. If I did something like `user.has_perm()`, things would blow up. But that is easy to override on your custom User class.

Fair enough.
 
> the context_processor will break due to the AnonymousUser most likely

Hmm, right...I suppose AnonymousUser could be refactored into base_user.py.

Yes, but we should keep an import in models.py for compatibility.

Matt

unread,
Mar 23, 2016, 9:56:42 PM3/23/16
to Django developers (Contributions to Django itself)
First pass (still haven't figured out how to test it):
https://github.com/satchamo/django/commit/d5accc17122cd7486a5e5fd2d63b4c1f732a5c68

It's not obvious from the diff, but AnonymousUser depends on permission stuff (see AnonymousUser._get_groups/_get_user_permissions). On top of that, AnonymousUser.get_all_permissions/has_perm/has_module_perms now have function level imports. I'm tempted to move the _user_has_perm/_user_get_all_permissions/_user_has_module_perms helpers into base_user too.

Aymeric Augustin

unread,
Aug 28, 2016, 4:43:36 AM8/28/16
to django-d...@googlegroups.com
On 23 Mar 2016, at 01:57, Matt <ma...@satchamo.com> wrote:

> I like to use the authentication machinery in Django, without explicitly putting 'django.contrib.auth' in INSTALLED_APPS. This prevents a bunch of unused tables from being creating in the database.



Hello,

For the record, we came to the following resolution on the related Trac ticket:

MIGRATION_MODULES = {
'auth': None
}

This trick also works for django.contrib.sessions if you don’t use the database or cached database backend.

--
Aymeric.

Mark Steward

unread,
Jul 23, 2017, 5:57:39 PM7/23/17
to Django developers (Contributions to Django itself)
And it was reverted with https://github.com/django/django/pull/7410 because of a link to ContentType.

I've recently run into this (as an infrequent user of Django) with a custom backend and middleware that I'd like to keep reusable by using the standard login and authenticate methods. I'm also using a custom user model, and so cutting the link to the auth app makes sense.

It seems like a cleaner way to tackle this is to separate out the reusable classes and functions from the auth app functionality, but that comes back to Matt's first question: is that something we want to support?


Mark
Reply all
Reply to author
Forward
0 new messages