To expand a little on @Suttonium’s answer - What you have done with the line
from . import views
is import views.py as a module named views.
(I’m being a little sloppy with my terminology here. I’m not being 100% precisely accurate - but it’s close enough for this discussion.)
So, when you want to use something within that module, you need to reference it through the module name.
In this case, there’s a function named index
defined in that file. Since the module is named views, a reference to that function would be views.index
.
This is different from just saying
import views
because that would import the function named index
into the current namespace. Not a good thing if you have two different functions named index
in two different modules and tried to import both modules into your current namespace.
Also be aware that you can change the name of a module when importing it using the as
clause on the import.
Let’s say that for whatever reason, you have three views all named index
in three different views.py
files in three different directories, but you want them all accessible at the same level URL level as index-1
, index-2
, and index-3
.
Your urls.py
file could look like this:
from django.urls import path
from app1 import views as views1
from app2 import views as views2
from app3 import views as views3
urlpatterns = [
path('index-1', views1.index, name='index1'),
path('index-2', views2.index, name='index2'),
path('index-3', views3.index, name='index3'),
]
(Now, I’m not saying you would ever really want to do this. This is just an illustrative example of using module imports to keep function namespaces separated.)