Opened 10 years ago
Last modified 4 years ago
#26401 new New feature
Allow auth machinery to be used without installing auth app
| Reported by: | Matt Johnson | Owned by: | |
|---|---|---|---|
| Component: | contrib.auth | Version: | 1.9 |
| Severity: | Normal | Keywords: | auth |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Django projects should be able to use the auth machinery (like django.contrib.auth.middleware.AuthenticationMiddleware and django.contrib.auth.context_processors.auth) without having django.contrib.auth in INSTALLED_APPS
See
https://groups.google.com/forum/#!topic/django-developers/2DzLBbk8w-w
This ticket is for resolving the current issue in 1.9. I also want to write a test or two to prevent this issue from happening in the future.
Attachments (1)
Change History (29)
comment:1 by , 10 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:2 by , 10 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:3 by , 10 years ago
| Has patch: | set |
|---|
comment:4 by , 10 years ago
| Needs tests: | set |
|---|
comment:5 by , 9 years ago
| Owner: | removed |
|---|---|
| Status: | assigned → new |
De-assigning so it's clear this is available for a PyCon sprinter to finish up with tests.
comment:6 by , 9 years ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:8 by , 9 years ago
FWIW I don't see a lot of value in adding this constraint. Implementing it requires a fragile and untestable combination of inner imports to avoid touching the models module.
If the only problem is to avoid creating tables in the database, add a MIGRATION_MODULES entry for the auth app that points to an empty package. I never tried it but I think it should work.
If this workaround is confirmed to work, I propose to close this ticket as wontfix.
comment:9 by , 9 years ago
Interesting idea. It works:
MIGRATION_MODULES = {
'auth': None
}
My complaint was driven by the unnecessary clutter in my database when using a custom user model. So now that there is a reasonable solution, I'm fine with closing this.
comment:10 by , 9 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | assigned → closed |
comment:12 by , 9 years ago
I found the above to be insufficient. Adding MIGRATION_MODULES as the only change to avoid the auth tables fails during migrations with the following trace:
Traceback (most recent call last):
File ".../manage.py", line 9, in <module>
execute_from_command_line(sys.argv)
File ".../venv/lib64/python3.5/site-packages/django/core/management/__init__.py", line 367, in execute_from_command_line
utility.execute()
File ".../venv/lib64/python3.5/site-packages/django/core/management/__init__.py", line 359, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File ".../venv/lib64/python3.5/site-packages/django/core/management/base.py", line 305, in run_from_argv
self.execute(*args, **cmd_options)
File ".../venv/lib64/python3.5/site-packages/django/core/management/base.py", line 356, in execute
output = self.handle(*args, **options)
File ".../venv/lib64/python3.5/site-packages/django/core/management/commands/migrate.py", line 222, in handle
self.verbosity, self.interactive, connection.alias, apps=post_migrate_apps, plan=plan,
File ".../venv/lib64/python3.5/site-packages/django/core/management/sql.py", line 53, in emit_post_migrate_signal
**kwargs
File ".../venv/lib64/python3.5/site-packages/django/dispatch/dispatcher.py", line 191, in send
response = receiver(signal=self, sender=sender, **named)
File ".../venv/lib64/python3.5/site-packages/django/contrib/auth/management/__init__.py", line 75, in create_permissions
"content_type", "codename"
File ".../venv/lib64/python3.5/site-packages/django/db/models/query.py", line 256, in __iter__
self._fetch_all()
File ".../venv/lib64/python3.5/site-packages/django/db/models/query.py", line 1085, in _fetch_all
self._result_cache = list(self.iterator())
File ".../venv/lib64/python3.5/site-packages/django/db/models/query.py", line 125, in __iter__
for row in compiler.results_iter():
File ".../venv/lib64/python3.5/site-packages/django/db/models/sql/compiler.py", line 789, in results_iter
results = self.execute_sql(MULTI)
File ".../venv/lib64/python3.5/site-packages/django/db/models/sql/compiler.py", line 835, in execute_sql
cursor.execute(sql, params)
File ".../venv/lib64/python3.5/site-packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File ".../venv/lib64/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File ".../venv/lib64/python3.5/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File ".../venv/lib64/python3.5/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File ".../venv/lib64/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "auth_permission" does not exist
LINE 1: ...ntent_type_id", "auth_permission"."codename" FROM "auth_perm...
This fails becuase the auth's AppConfig adds a post_migrate callback that requires the auth_permission table to exist. A project could avoid this by overriding the auth's AppConfig. I think this could be easier for projects if the auth's AppConfig was split into two classes, one base version that can be used without the auth tables and one that matches the current implementation. This would be a backwards compatible change that would allow the MIGRATION_MODULES change noted above. For example:
class BaseAuthConfig(AppConfig):
name = 'django.contrib.auth'
verbose_name = _("Authentication and Authorization")
def ready(self):
checks.register(check_user_model, checks.Tags.models)
class AuthConfig(BaseAuthConfig):
def ready(self):
post_migrate.connect(
create_permissions,
dispatch_uid="django.contrib.auth.management.create_permissions"
)
checks.register(check_models_permissions, checks.Tags.models)
comment:13 by , 9 years ago
| Resolution: | wontfix |
|---|---|
| Status: | closed → new |
comment:14 by , 9 years ago
PR implementing the AppConfigs described above.
Not sure how to best add a test for this though. Looking for advice. Details in the PR.
comment:16 by , 9 years ago
| Easy pickings: | unset |
|---|---|
| Patch needs improvement: | set |
comment:17 by , 9 years ago
| Patch needs improvement: | unset |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
comment:19 by , 9 years ago
I've hit another snag with the MIGRATION_MODULES = {'auth': None} approach. (Sorry, is it better to reopen this ticket or file a new one?)
The auth.Permission model has a fk on ContentType. Due to this, when deleting a ContentType (such as with the remove_stale_contenttypes command) queries against the missing auth_permission table can occur.
Not sure how best to handle this scenario. IIUC, as long as auth is in INSTALLED_APPS, the models will be loaded and this FK will cause an issue.
Here is a stack trace when deleting a stale content type
Traceback (most recent call last):
File "/usr/lib64/python3.5/runpy.py", line 170, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib64/python3.5/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/jon/devel/django/django/__main__.py", line 9, in <module>
management.execute_from_command_line()
File "/home/jon/devel/django/django/core/management/__init__.py", line 366, in execute_from_command_line
utility.execute()
File "/home/jon/devel/django/django/core/management/__init__.py", line 358, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/jon/devel/django/django/core/management/base.py", line 294, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/jon/devel/django/django/core/management/base.py", line 345, in execute
output = self.handle(*args, **options)
File "/home/jon/devel/django/django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py", line 46, in handle
collector.collect([ct])
File "/home/jon/devel/django/django/db/models/deletion.py", line 218, in collect
elif sub_objs:
File "/home/jon/devel/django/django/db/models/query.py", line 260, in __bool__
self._fetch_all()
File "/home/jon/devel/django/django/db/models/query.py", line 1072, in _fetch_all
self._result_cache = list(self.iterator())
File "/home/jon/devel/django/django/db/models/query.py", line 54, in __iter__
results = compiler.execute_sql()
File "/home/jon/devel/django/django/db/models/sql/compiler.py", line 847, in execute_sql
cursor.execute(sql, params)
File "/home/jon/devel/django/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/jon/devel/django/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/jon/devel/django/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/home/jon/devel/django/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/jon/devel/django/django/db/backends/sqlite3/base.py", line 334, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: auth_permission
by , 9 years ago
| Attachment: | ticket-26401-remove-stale-contenttypes.patch added |
|---|
Test case for remove_stale_contenttypes with auth migrations disabled
comment:20 by , 9 years ago
| Has patch: | unset |
|---|---|
| Keywords: | 1.11 added |
| Triage Stage: | Ready for checkin → Accepted |
| Type: | Bug → New feature |
It's appropriate to reopen a ticket if the fix hasn't been released yet.
comment:21 by , 9 years ago
| Resolution: | fixed |
|---|---|
| Status: | closed → new |
Reopening until the above issue is handled.
comment:22 by , 9 years ago
| Has patch: | set |
|---|
I'm unable to think of a sensible solution to the ContentType auth.Permission dependency issue. Therefore, I'm suggesting to revert my previous PR as using auth without migrations will not fully work.
comment:23 by , 9 years ago
It seems like you basically want an apps.register.Apps.unregister_model() method or some way of telling Django not to setup relations for a given model. This might not be trivial, so if you want to revert for now, that's fine with me.
comment:25 by , 9 years ago
| Resolution: | fixed |
|---|---|
| Status: | closed → new |
Reopening. The revert commit was merged.
comment:26 by , 9 years ago
| Has patch: | unset |
|---|---|
| Keywords: | 1.11 removed |
comment:27 by , 4 years ago
| Owner: | removed |
|---|---|
| Status: | new → assigned |
comment:28 by , 4 years ago
| Status: | assigned → new |
|---|
https://github.com/django/django/pull/6420