13đź‘Ť
In the second project you’ve probably already imported the auth.views
module before calling auth.views.login
. Python stitches your imported modules when it can.
For example, this will work
>>> from django.contrib.auth.views import login #or from django.contrib.auth import views
>>> from django.contrib import auth
>>> auth.views.login
<function login at 0x02C37C30>
The first import doesn’t even have to mention the login
view. This will also work.
>>> from django.contrib.auth.views import logout
...
#then import auth.views.login
The following won’t because python does not know of the views
module since it isn’t registered in auth.__init__.py
>>> from django.contrib import auth
>>> auth.views.login
...
AttributeError: 'module' object has no attribute 'views'
1đź‘Ť
In the first import (from django.contrib.auth.views import login
), the dot syntax is traversing the module hierarchy. In the urlpattern access (auth.views.login
), the dot-syntax is doing property (ie. class) lookup. From my shell_plus, you can see that “auth” doesn’t have a views property.
In [1]: from django.contrib import auth
In [2]: auth.<TAB FOR COMPLETION>
auth.BACKEND_SESSION_KEY auth.load_backend
auth.ImproperlyConfigured auth.login
auth.PermissionDenied auth.logout
auth.REDIRECT_FIELD_NAME auth.models
auth.SESSION_KEY auth.re
auth.authenticate auth.rotate_token
auth.forms auth.settings
auth.get_backends auth.signals
auth.get_permission_codename auth.tokens
auth.get_user auth.user_logged_in
auth.get_user_model auth.user_logged_out
auth.hashers auth.user_login_failed
auth.import_by_path
This is why it’s giving you an error. It really shouldn’t work if you’re trying that in another project/file either — unless your other project’s auth.__init__.py
is auto-loading its submodules.