Django serve static index.html with view at '/' url

DjangoDjango ViewsDjango Staticfiles

Django Problem Overview


I have my index.html in /static/ folder. My django app is running ok when i try:

http://127.0.0.1:8000/index.html

But i want to acces index.html by url:

http://127.0.0.1:8000/

I wrote a view and it works:

class IndexView(TemplateView):
    template_name = 'index.html'

I also added to urls.py(this lets me serve static like http://127.0.0.1:8000/css/style.css):

url(r'^(?P<path>.*)$', 'django.contrib.staticfiles.views.serve', {
            'document_root': settings.STATIC_ROOT, 'show_indexes':True
        }),

But i think there is a way to do what i want without TemplateView.

Any suggestions? Thanks. My django version is: Django 1.5

EDIT:

The reason i placed index.html into static: i want to make Phonegap compatible django app, so after proper coding, all i have to do is --> make .zip from static folder and upload it to Phonegap as mobile app. Easy and clean.

Django Solutions


Solution 1 - Django

You can serve static/index.html for development like this:

if settings.DEBUG:
    urlpatterns += url(
        r'^$', 'django.contrib.staticfiles.views.serve', kwargs={
            'path': 'index.html', 'document_root': settings.STATIC_ROOT}),

But for production you should configure your nginx (or other frontend server) to serve index.html file for / location

UPDATE

I want to explain the case you should do like this. For example your django app is only admin and api view, but client interacts with a single page app (Ember, Angular, whatever). So you project has at least two subprojects, one with your main django app and the second is a client app with all html/js/css stuff. It is very convenient to have client scripts separate from django backend, it allows your frontend developers to do their job and avoid django existence (someday it can be moved to the distinct repo).

So in this case you get the following build workflow:

  1. Run client app sources watcher to rebuild your scripts/styles/templates (brunch watch, grunt job or gulp watch task)
  2. Collect static with django for production
  3. Make sure you have urlpatterns fix for developments and right nginx config for production

Here is my urls.py example

urlpatterns += patterns(
    'django.contrib.staticfiles.views',
    url(r'^(?:index.html)?$', 'serve', kwargs={'path': 'index.html'}),
    url(r'^(?P<path>(?:js|css|img)/.*)$', 'serve'),
)

Solution 2 - Django

You don't need to subclass TemplateView in this case. You can use TemplateView directly in your url conf, as long as index.html is in your templates directory.

from django.views.generic.base import TemplateView

urlpatterns = [
    url(r'^$', TemplateView.as_view(template_name='index.html'), name="home"),
]

Solution 3 - Django

Check out my long explanation of how to serve index.html on / in this answer (or extended as a blog post). That solution alone might not be sufficient, however, if you want to have a full-fledged SPA served by Django (because you need frontend routing).

I've been playing with different methods for routing /static/ to /, forwarding all requests to the frontend, finding index.html files. In the end I found the best method to solve all of this was not by tweaking urls.py, but as an extension of WhiteNoise that I released as django-spa (installation instructions in the README).

You can find some of the related discussion in this WhiteNoise issue.

Solution 4 - Django

Just wrap your static HTML file in an iframe defined in a templated HTML file. With some style tweaks can make the iframe 100% width and height.

{% load static %}
<html>
    <head>
        <title>Templated HTML</title>

        <style>
            html, body {
                width: 100%;
                width: 100%;
                margin: 0;
                padding: 0;
                border-width: 0;
            }

            iframe {
                position: absolute;
                top: 0;
                left: 0;
                width: 100vw;
                height: 100vh;
                margin: 0;
                padding: 0;
                border-width: 0;
            }
        </style>
    </head>
    <body>
        {{ content }}
        <iframe src="{% static 'main/html/test.html' %}"></iframe>
    </body>
</html>

Solution 5 - Django

you can create templates directory, put the html there and then render it from views.py

    def index(request):
        return render(request, 'my_app/index.html', context={})

dont forget to set the templates_dir in the settings.py

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES_DIR = os.path.join(BASE_DIR, "templates")

TEMPLATES = [
{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [TEMPLATES_DIR,],
    'APP_DIRS': True,
    ...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFeanorView Question on Stackoverflow
Solution 1 - DjangoAnton EgorovView Answer on Stackoverflow
Solution 2 - DjangoAlasdairView Answer on Stackoverflow
Solution 3 - DjangometakermitView Answer on Stackoverflow
Solution 4 - DjangoGeordieView Answer on Stackoverflow
Solution 5 - DjangoMichael ObichkinView Answer on Stackoverflow