May, 2023 Update:
templates folder can be put just under django-project folder or just under each app folder as shown below:
django-project
|-core
│ |-settings.py
│ └-urls.py
|-app1
| |-urls.py
| └-views.py
|-app2
| |-urls.py
| └-views.py
└-templates # Here
|-app1
| └-a1.html
└-app2
└-a2.html
Or:
django-project
|-core
│ |-settings.py
│ └-urls.py
|-app1
| |-urls.py
| |-views.py
| └-templates # Here
| └-app1
| └-a1.html
└-app2
|-urls.py
|-views.py
└-templates # Here
└-app2
└-a2.html
For example first, you need set "app1" and "app2" to INSTALLED_APPS in settings.py as shown below:
# "core/settings.py"
INSTALLED_APPS = [
...
"app1",
"app2",
]
Then if templates folder is just under django-project folder as shown below:
django-project
|-core
│ |-settings.py
│ └-urls.py
|-app1
| |-urls.py
| └-views.py
|-app2
| |-urls.py
| └-views.py
└-templates # Here
|-app1
| └-a1.html
└-app2
└-a2.html
Then, you need to set BASE_DIR / 'templates' to "DIRS" in TEMPLATES in settings.py as shown below. *I recommend to put templates folder just under django-project folder as shown above because you can easily manage templates in one place:
# "core/settings.py"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
BASE_DIR / 'templates' # Here
],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
And, if templates folder is just under each app folder as shown below:
django-project
|-core
│ |-settings.py
│ └-urls.py
|-app1
| |-urls.py
| |-views.py
| └-templates # Here
| └-app1
| └-a1.html
└-app2
|-urls.py
|-views.py
└-templates # Here
└-app2
└-a2.html
Then, you need to keep "DIRS" empty (which is default) without setting BASE_DIR / 'templates' to "DIRS" in TEMPLATES in settings.py as shown below:
# "core/settings.py"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [], # Keep it empty
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
Then, define test() in app1/views.py and app2/views.py as shown below. Be careful, you need to set "app1/a1.html" and "app2/a2.html" instead of just setting "a1.html" and "a2.html" in render() as shown below:
# "app1/views.py"
from django.shortcuts import render
def test(request): # Don't set just "a1.html"
return render(request, "app1/a1.html")
# "app2/views.py"
from django.shortcuts import render
def test(request): # Don't set just "a2.html"
return render(request, "app2/a2.html")
Then, set each test view of app1 and app2 in app1/urls.py and app2/urls.py as shown below:
# "app1/urls.py"
from django.urls import include, path
from . import views
app_name = "app1"
urlpatterns = [
path("", views.test, name='test'), # Here
]
# "app2/urls.py"
from django.urls import include, path
from . import views
app_name = "app2"
urlpatterns = [
path("", views.test, name='test'), # Here
]
Then, set each urls.py of app1 and app2 in core/urls.py as shown below, then the templates of app1 and app2 will be rendered without any errors:
# "core/urls.py"
from django.urls import include, path
urlpatterns = [
...
path("app1/", include('app1.urls')), # Here
path("app2/", include('app2.urls')) # Here
]
Lastly again, I recommend to put templates folder just under django-project folder as shown below because you can easily manage templates in one place:
django-project
|-core
│ |-settings.py
│ └-urls.py
|-app1
| |-urls.py
| └-views.py
|-app2
| |-urls.py
| └-views.py
└-templates # Here
|-app1
| └-a1.html
└-app2
└-a2.html