0

The asterisk (*) is used as a wildcard in from modue_name import *,it means import all sub modules in the module_name.

ls /usr/local/lib/python3.5/dist-packages/django
apps  contrib  dispatch  __init__.py  __pycache__   templatetags  utils
bin   core     forms     __main__.py  shortcuts.py  test          views
conf  db       http      middleware   template      urls

The sub module apps located in django module.

import django
from django import *
print(django.apps)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'django' has no attribute 'apps'

Why the sub module apps can't be imported by from django import *?

4 Answers4

1

The asterisk (*) is used as a wildcard in from modue_name import *,it means import all sub modules in the module_name.

Sort of.

Module

The asterisk when used in from <module_name> import *. will import everything inside the module if we are talking about a single module(a single file something like tools.py). this kind of module does not have sub_modules so It wouldn't makes sense to say

it means import all sub modules in the module_name.

Package

However here we are dealing with a package named django; it has a __init__.py (In Python 3.3 and above packages don't need a __init__.py file) file so it is a package. in this case calling from <package_name> import * will import everything inside the __init__.py file of the package but by default it will not import other sub_modules inside the package unless you define a __all__ list and include inside it the name of the sub_modules, objects and sub_packages you would like to be exported by the sub_package (this is the work of the vendor of the package). i.e

# __init__.py
__all__ = ['apps']

the package can also explicitly import the sub_moudules/sub_packages/objects inside it's __init__.py and that makes the sub_moudule available when using the from <package_name> import * syntax i.e

# __init__.py
import django.apps

again this is the work of the vendor.

Solution

But from you side of the code you should simply type

from django.apps import <what_you_need>

It's much cleaner

masonCherry
  • 894
  • 6
  • 14
0

If you want to use the apps module in your context, you can do it two ways (at least)

Method-1

import django.apps

print(django.apps)

Note: it should be import django.apps instead of import django

Method-2

from django import apps

print(apps)

When you use from django import *, Python will import only the modules (fles that has extension .py) and the __init__.py . ie, the apps won't be available since its not a module but a package

JPG
  • 82,442
  • 19
  • 127
  • 206
0

Firstly, it's always a good idea to install requirements into virtual environments, instead of system Python. It worth to note that starting from Python 3.3 the venv module was added that makes this process straightforward.

The error you're getting related to the process of handling modules in Django. Actually there is a difference between the result of the example when running in the default console and in Django shell. Consider this example:

# globally load the module, let's check what's inside.
>>> import django
>>> dir(django)  # only the content from the __init__.py was imported.
['VERSION', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
 '__name__', '__package__', '__path__', '__spec__', '__version__', 
'get_version', 'setup', 'utils']
>>> from django import *
>>> print(django.apps)
>>> Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'django' has no attribute 'apps'

>>> globals() # no Django submodules were loaded. 

In the same time running the commands above in the Django shell:

>>> import django
>>> dir(django)
['VERSION', '__builtins__','__cached__','apps','setup','template',
'templatetags','urls','utils', 'views', ...]
>>> print(django.apps)
>>> <module 'django.apps' from .../django/apps/__init__.py>
>>> globals() # some of the Django submodules were loaded 

When you make global Django import in the console, all the content from the __init__.py will be loaded and there is no direct import of Django submodules inside. But Django shell on the first django import makes availability of submodules as well.

funnydman
  • 9,083
  • 4
  • 40
  • 55
0

There is no __all__ list in django/__init__.py. That is why the wildcard import from django import * does not work.

See https://docs.python.org/3/tutorial/modules.html#importing-from-a-package and Can someone explain __all__ in Python?.

mzjn
  • 48,958
  • 13
  • 128
  • 248
  • In `__all__` we just specify the modules that are "publicly" available. It's some sort of declaration to say which modules you should use and hide "private" but it still the way to access them by name. Also, `__all__` does not import modules for you, you need to load them normally and after that specify their names in the `__all__` attribute. – funnydman Dec 22 '19 at 08:06
  • @funnydman: All I'm saying is that for wildcard imports to work, there has to be an `__all__` list. There is no such list in this case. Therefore,`from django import *` does not work. – mzjn Dec 22 '19 at 08:11
  • There is no need to have `__all__` to use wildcards imports. Did I miss something? – funnydman Dec 22 '19 at 08:16
  • `cat /usr/local/lib/python3.5/dist-packages/django/__init__.py |grep __all__` –  Jan 26 '20 at 09:42
  • `__all__ = ['apps','db']` –  Jan 26 '20 at 09:42
  • No `app` in `__all__`,instead of no `__all__` list. –  Jan 26 '20 at 09:44