“Hello World” using Django Template

In today’s event loop on {{ PLP }}, things getting warmer each time we have a new topic to discuss with.  So, for a brief recall to our previous event loop, we learn about how to structure Django projects with better sustainability and a pluggable app ready for faster deployment to our various Django projects.

Introduction

Welcome to the “Hello World” in Django template and this is just one of the basic usage of Django and Python programming.  So, let’s begin with printing out the “Hello World” which is the famous phrase in the programming world.

You’re about to learn to display simple text to an HTML page in the web browser, so, get ready and stay focus, because it’s the very foundation of the Django template and if you can’t display anything in the web browser, our efforts in learning with Django and Python will be in vain as well.

Getting Started

First of all, in Python’s version of “Hello World is very easy to execute in the console.

1
2
print("Hello World!")
Hello World!

And another example using a variable like this.  That’s easy right?

1
2
3
name = 'Johnny Bravo'
print(name)
Johnny Bravo

But how we can do this in Django Template?

In order for us to display the “Hello World” context in an HTML page, we need to use the Django template, here’s how.

Step 1: Follow the Ideal Django Project Structure

I assume that you still have the project structures in your development PC as we’ve learned earlier about “The Ideal Django Project Structures“.

Step 2:  Modify your settings.py

We need to set up a few things from our settings.py, open it using your preferred text editor, but I preferred to use Atom and head over to their website and install it accordingly.  So, below is the content of the settings.py found in “dev/dev” folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""
Django settings for dev project.

Generated by 'django-admin startproject' using Django 2.1.1.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""


import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'YOUR SECRET KEY HERE'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['.pinoylearnpython.com', '172.104.190.249']


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'dev.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]

WSGI_APPLICATION = 'dev.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'

Look for “ALLOWED_HOSTS” and key-in your domain name with a dot in front to accept subdomains from a specified domain name only as one of the web security precautionary measures and include your web server IP address as well.

Other configurations you need to change accordingly for SECRET_KEYROOT_URLCONF and WSGI_APPLICATION.  The “.dev” is actually my project name but in your case, you can always change based on your project name.

IMPORTANT NOTE:  The “DEBUG = True” from your settings.py set to true only when you’re still in the development stage, but for production server you must set this to False to prevent any unintended errors that might display to the anonymous users.  So, please be careful.

Step 3:  Install Django Channels

In order for us to use the Asynchronous method, access your console first and execute this command.

1
pip3 install -U channels

So, it should be smooth installation process.  As I’ve mention from our previous topic about using the Asynchronous method.

Step 4:  Include “channels” to your INSTALLED_APPS from your settings.py

1
2
3
4
5
6
7
8
9
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',
]

You must insert it after any Django default configurations.

Step 5:  Create a new “routing.py” inside the “dev/dev” folder.

Please don’t rename this “routing.py” file to any other name as this is the naming convention given by the Django channels application.

1
2
3
4
5
6
7
8
9
10
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack

application = ProtocolTypeRouter({
    "websocket": AuthMiddlewareStack(
        URLRouter([
            # URLRouter just takes standard Django path() or url() entries.
        ]),
    ),
})

So, copy exactly the code above for routing.py file.

Step 6:  Insert this line of code to your “settings.py” below the AUTH_PASSWORD_VALIDATORS.

Because, I preferred to insert this line of code below the AUTH_PASSWORD_VALIDATORS section of the settings.py to group all major configurations there.

1
2
# ASGI_APPLICATION should be set to your outermost router
ASGI_APPLICATION = 'dev.routing.application'

But, of course, you can always insert anywhere from the settings.py as your own preferred spot.

Step 7:  Install Redis Backend for Django Channels

1
pip3 install -U channels_redis

The Redis backend installation should be running smooth for Django channels 2.0 requirement.

Step 8:  Insert this line of code to your “settings.py” below the ASGI_APPLICATION.

Just insert this code from your settings.py and please change the “prefix” to your own app name or project name respectively and the “port” number just leave it like that as the default redis port number but you can always use other port number, it’s up to you, but for now just leave it like that.

1
2
3
4
5
6
7
8
9
10
11
12
13
# Channels-specific settings
redis_host = os.environ.get('localhost')

CHANNEL_LAYERS = {
    "default": {
        # This example app uses the Redis channel layer implementation channels_redis
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [(redis_host, 6379)],
            "prefix": "PLP",
        },
    },
}

Experience Tip:  Based on my own experienced, when you’ve multiple Django projects running on the same web server, avoid using the same Redis port number for your other Django projects, so that the scheduled running tasks in Celery not able to display and function it correctly and in-app real-time monitoring which is called the “Flower” will not be able to display all the lists of scheduled tasks with the conflicting Redis port number.

So, please remember this very important configuration about the Redis port number assignment.

Step 9:  Create a new file called “asgi.py” inside the “dev/dev” folder.

And copy this entire codes below and then save it, but please, don’t rename the file as this is the naming convention that use primarily for Django channels 2.0.

1
2
3
4
5
6
7
8
9
10
11
12
"""
ASGI entrypoint. Configures Django and then runs the application
defined in the ASGI_APPLICATION setting.
"""


import os
import django
from channels.routing import get_default_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dev.settings")
django.setup()
application = get_default_application()

Again, please don’t remove the wsgi.py and instead you must have asgi.py to use the Django channels 2.0 asynchronous method.

Step 10:  Open the “vmain.py” located at “dev/myroot/views/”.

Why we use the request.method == “GET” and not the method == “POST”?  It’s because, we are retrieving information from the web server and not submitting any requests to store any information or data to be inserted in the database or upload any files to the web server.

The “def” is actually a Python function format and we need to call this function each time someone request to display the “Hello World” HTML page.

1
2
3
4
5
6
7
8
9
10
from django.conf import settings
from django.shortcuts import render


def hello_world_view(request):
    """Renders the Hello World page."""
    if request.method == 'GET':
        return render(request, 'myroot/hello_world.html',
                      {'title': 'Hello World!',
                       'BASE_URL': settings.BASE_URL})

Then copy exactly the code above and paste it to the “vmain.py” file.

As you can see, we import the “from django.shortcuts import render” on the very top of the code snippets for us to use the “render” method from Django to load the “myroot/hello_world.html” file which is located at the “dev/myroot/templates/myroot/” with a few extra pieces of baggage which are the context variable assignments to be used and load to the “hello_world.html” later on.

Why do the templates repeat the “myroot” folder structure? It’s because, that’s how Django templates works and uniquely identify the template folder ownership in each app and don’t rename it as your HTML files may not be loaded properly.

Also, insert this code below to your settings.py file located at “dev/dev” folder.

1
2
3
4
5
# *******************************************
# My custom configurations
# *******************************************
# For base url, include "/" at the end
BASE_URL = 'https://dev.pinoylearnpython.com/'

Step 11:  Register the “helloworld” link using urls.py from Django.

But, before we can see the “Hello World” context from an HTML page that we’ve created earlier, we need to register this new link from the urls.py provided by Django.  Locate the file from the “dev/dev” folder.

1
2
3
4
5
6
7
8
9
10
11
from django.contrib import admin
from django.urls import path

# Call myroot properties
import myroot.views.vmain


urlpatterns = [
    path('admin/', admin.site.urls),
    path('helloworld/', myroot.views.vmain.hello_world_view, name='helloworld'),
]

Insert that line of code below the “path(‘admin/’, admin.site.urls),” and always end with “,” comma symbol at the end of each line to indicate that this is a list comprehension requirement from Python.

The “helloworld/” that ends with “/” is basically required by Django and the “myroot.views.vmain” is the actual file path from which your “hello_world_view” is located to call that Python function to be executed when someone accessing the “helloworld” link.

Step 12:  Register the “myroot” app to your INSTALLED_APPS in the settings.py

Please take note that every time you’ve a new app or want to include installed external app, you must insert it to the INSTALLED_APPS, always.

1
2
3
4
5
6
7
8
9
10
INSTALLED_APPS = [
    'myroot',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',
]

Step 13:  Register the “myroot” app configuration to the “apps.py” 

Copy this code to the dev/myroot/apps.py and paste the code below.

1
2
3
4
5
6
7
from django.apps import AppConfig
from django.conf import settings


class myrootConfig(AppConfig):
    """ Class to call our 'myroot' app structural name """
    name = settings.APP_LABEL_MYROOT

Step 14:  Insert this line of code to the “settings.py”

This is in relation to the apps.py calling the settings.APP_LABEL_MYROOT from the settings.py file just insert this line of code under “My custom configurations” section to group our own configurations.

When you’ve multiple apps included in the INSTALLED_APPS, you also need to create the “APP_LABEL_” plus the app name to organize properly every Apps we have.

1
2
3
4
5
# *******************************************
# My custom configurations
# *******************************************
# For app labels section here
APP_LABEL_MYROOT = 'myroot'

Step 15:  Prepare the HTML page to be used in Django Template.

We’re almost done, don’t worry about it, and just be with me as this is the first time we set up everything.  So, now, the HTML page creation is composed of the basic layout like the HTML header, the body of an HTML page and the footer section as well.

The basic structure of an HTML page without using the Django template would look like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Your Page Title here</title>
        <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
        <meta name="description" content="Your page meta description here" />
        <link rel="icon" type="image/jpg" href="/your/path/to/favicon.ico">
    </head>
    <body>
        <h1>Your content title here</h1>
        <p>My long content will be here as well.</p>
        <footer class="my_footer_class_here">
            <p>My company year started here or any footer menus here.</p>
        </footer>
    </body>
</html>

The traditional way of creating a new page and the basic HTML structures keep repeating all over again every time we need to create a page for our project.

Now, because of Django template, we can eliminate the tedious process each time the HTML page created.  In Django template, we need to create one basic HTML layout which consists of the following.

Under “dev/myroot/templates/myroot/” path, the base layout for HTML will be kept there.

layout_home.html

The “layout_home.html” file consist of the skeletal framework that can be use as the standard HTML format for a certain HTML patterns and design as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>{{ title|slice:":60" }}</title>
    <link rel="canonical" href="{{ BASE_URL|slice:":-1" }}{{ request.get_full_path }}">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <meta name="description" content="{{ meta_desc|slice:":160" }}" />
    {% load static %}
    <link rel="icon" type="image/jpg" href="{% static 'assets/images/favicon.ico' %}">
    <link rel="stylesheet" href="{% static 'bootstrap4/css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'fontawesome5/css/fontawesome-all.min.css' %}">
    <link rel="stylesheet" href="{% static 'assets/css/common.css' %}">
    <style>
        .hero {min-height: 100px; position: relative; z-index: 10; text-align: center; padding-top: 10px;}
    </style>
    {% block extra_styles_head %}{% endblock %}
</head>

{% block body_styles %}
<body class="bg-light">

    {% block page_sub_title %}{% endblock %}

    <main role="main">
        {% block content %}{% endblock %}
        <script src="{% static 'assets/js/common/jquery.min.js' %}"></script>
        <script src="{% static 'bootstrap4/js/popper.min.js' %}" defer></script>
        <script src="{% static 'bootstrap4/js/bootstrap.min.js' %}" defer></script>
        <script src="{% static 'bootstrap4/js/holder.min.js' %}" defer></script>

        <!-- Global site tag (gtag.js) - Google Analytics -->
        <script async src="https://www.googletagmanager.com/gtag/js?id=UA-126199598-1"></script>
        <script>
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());

          gtag('config', 'UA-126199598-1');
        </script>
        {% block scripts %}{% endblock %}

        {% block footer %}
            {% include 'myroot/footer_home.html' %}
        {% endblock %}
    </main>

    {% block extra_styles_bottom %}{% endblock %}
</body>
{% endblock %}
</html>

Basically, the base HTML is quite simple and very straightforward and easily can understand with.  We’re using few common HTML design framework which is the bootstrap 4, fontawesome for free icons, standard jquery library and my own CSS styling, just a basic of it.

The Django command to load the static files like the Javascript, CSS and images is the “{% load static %}” before any static assets being called in your HTML.

Another Django command as you’ve seen it is the “{% block your_block_name_here%}{% endblock %}” followed by the block name you’ve given and that your own block name must be unique because you need to insert HTML tags or contents on that section from the “layout_home.html” file.

footer_home.html

For now, our footer would be very simple as well just to showcase how we can call the footer_home.html from the layout_home.html.

1
2
3
<footer class="my-1 pt-2 text-muted text-center text-small">
    <p class="mt-1 mb-1 text-muted text-center">This is a simple footer section.</p>
</footer>

Have you noticed how we call this “footer_home.html” from the “layout_home.html” file?  Yes, exactly, we need to use another Django Template command which is the “{% include ‘path/to/your/file/myfile.html %}‘ followed by the file path to call internal HTML file and merge it together from our base HTML.

Step 16:  Create an HTML file called “hello_world.html” under “dev/myroot/templates/myroot/”

Now, the most awaited part is finally here, copy this HTML scripts for us to see the famous “Hello World” and yeah, welcome to our programming world.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{% extends "myroot/layout_home.html" %}
{% load static %}

{% block schema_json %}{% endblock %}

{% block content %}
    <div class="jumbotron">
        <div class="container">
            <h1 class="display-3">Hello, world!</h1>
            <p>Hello World using Direct HTML page.</p>
            <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more »</a></p>
        </div>
    </div>

    <div class="jumbotron">
        <div class="container">
            <h1 class="display-3">{{ title }}</h1>
            <p>Hello World using Django Context Variable.</p>
            <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more »</a></p>
        </div>
    </div>
{% endblock %}

{% block scripts %}
<script src="{% static 'assets/js/common/common.js' %}" defer></script>

<script defer>

    var BASE_URL = "{{ BASE_URL }}";
    var COMMON_ASSETS_URL = "{% static 'assets/images/' %}";
    var THIS_OBJ = '';

</script>
{% endblock %}

The few Django template commands have been mixed with the standard HTML tags, like the {% extends “myroot/layout_home.html” %}  that load first our “layout_home.html” file and then insert the “hello_world.html” contents.

One more thing you’ve noticed is that the structure of the “hello_world.html” is not the full standard HTML page structure with the HTML headers, the body, and the footer as well that’s because it’s being there at the “layout_home.html” contents already.

This “{{ title }}” is actually our Django context variable that we stored the word “Hello World!” on step no. 10 earlier and now, we wanted to display this on our HTML page and you need to wrap that context variable with the “{{ }}” open and closed parenthesis.

Step 17:  Upload all new and modified files to the Web Server using FileZilla.

Now, the best part is to upload all the modified and the new files to our web server as well, we need to use the FileZilla, in case you forget on how to use the FileZilla, please do a quick check on our previous event loop on “How to Install FileZilla“.

Step 18:  Setup NGINX web server with few changes to serve our subdomain and our development project.

I preferred to use the FileZilla to open and modify the NGINX file, download the NGINX folder at “/etc/nginx” and look for the “/etc/nginx/nginx.conf” file and insert replace with this code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
  worker_connections 4096;
  # multi_accept on;
}

http {

  ##
  # Basic Settings
  ##

  etag on;
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  types_hash_max_size 2048;

  # MY CUSTOM SETTINGS
  server_tokens off;
  client_max_body_size 750M;
  proxy_connect_timeout 300;
  proxy_send_timeout 300;
  proxy_read_timeout 300;

  # server_names_hash_bucket_size 64;
  # server_name_in_redirect off;

  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  ##
  # SSL Settings
  ##

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
  ssl_prefer_server_ciphers on;

  ##
  # Logging Settings
  ##

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  ##
  # Gzip Settings
  ##

  gzip on;
  gzip_disable "msie6";

  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 5;
  gzip_min_length 256;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;

  gzip_types
      application/atom+xml
    application/javascript
      application/json
      application/ld+json
      application/manifest+json
      application/rss+xml
      application/vnd.geo+json
    application/vnd.ms-fontobject
      application/x-font-ttf
      application/x-web-app-manifest+json
      application/xhtml+xml
      application/xml
      font/opentype
      image/bmp
      image/svg+xml
      image/x-icon
      text/cache-manifest
      text/css
    text/plain
      text/vcard
      text/vnd.rim.location.xloc
      text/vtt
      text/x-component
      text/x-cross-domain-policy;
  ##
  # Virtual Host Configs
  ##

  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;

  server {

    root /var/www/html;
    index index.php, index.html index.htm;
    charset utf-8;
    add_header "X-UA-Compatible" "IE=Edge,chrome=1";

    location / {
      try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
          try_files $uri =404;
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass unix:/run/php/php7.2-fpm.sock;
          fastcgi_index index.php;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include fastcgi_params;
      }
  }
}


#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
#   listen     localhost:110;
#   protocol   pop3;
#   proxy      on;
# }
#
# server {
#   listen     localhost:143;
#   protocol   imap;
#   proxy      on;
# }
#}

Step 19:  Create the new file called “dev.pinoylearnpython.com” under “nginx/sites-available”.

Now, in my case, I created the “dev.pinoylearnpython.com” for us to set up our development testing web server.  But, in your case, you can set up your own with the same NGINX configuration below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
server {

  listen 80;
  listen [::]:80;

  server_name dev.pinoylearnpython.com;

  root /var/www/html/dev.pinoylearnpython.com/public_html;
  index index.php index.html index.htm;

  location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    include fastcgi_params;
    fastcgi_pass unix:/run/php/php7.2-fpm.sock;
    fastcgi_param SCRIPT_FILENAME /var/www/html/dev.pinoylearnpython.com/public_html$fastcgi_script_name;
  }

  # For connection time out issue
  # Ref: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_connect_timeout
  location / {
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_pass http://172.104.190.249:8000;
  }

  location /static/ {
    alias /var/www/html/dev.pinoylearnpython.com/public_html/static/;
  }

  location /robots.txt {
    alias /var/www/html/dev.pinoylearnpython.com/public_html/static/robots.txt;
    access_log        off;
    log_not_found     off;
  }

  location /googleb75a09842fe5c750.html {
    alias /var/www/html/dev.pinoylearnpython.com/public_html/static/googleb75a09842fe5c750.html;
    access_log        off;
    log_not_found     off;
  }

  location ~*  \.(jpg|jpeg|png|gif|ico|css|js|pdf|ttf|ttc|otf|eot|woff|woff2)$ {
    expires 7d;
  }

  # this prevents hidden files (beginning with a period) from being served
  location ~ /\. {
    access_log        off;
    log_not_found     off;
    deny              all;
  }
}

The things you need to modify in your case are the following:

This line server_name dev.pinoylearnpython.com; which you can change with your own domain name or subdomain name.

Another config you need to change is the proxy_pass http://172.104.190.249:8000;  which of course your own web server IP address and the 8000 is the Django default port number, but you can always change this port number with your own.

Then you can create a new public folder under “/var/www/html/dev.pinoylearnpython.com/public_html/static” and then upload all your static assets like the Javascript, CSS, and images only.

Replace all the necessary static address base on your own web static full path address.

Step 20:  Upload your modified NGINX files under “/etc/nginx”.

Upload and replace 1 modified file under “nginx/nginx.conf” to the web server at “etc/nginx” and the new file from “nginx/sites-available/dev.pinoylearnpython.com” as well.

But, in your case, you can copy the “default” file there and paste in the same path and rename with your own domain name or subdomain name accordingly.

After you’ve done the upload of your NGINX files, open your web console with the root access privilege.

To enable our newly created website address to be accessible and serve by our NGINX web server.

1
sudo ln -s /etc/nginx/sites-available/dev.pinoylearnpython.com /etc/nginx/sites-enabled/

We need to restart our NGINX web server and execute this command.

1
sudo systemctl reload nginx

Give your application the full right access to your “var/www” folder.

1
sudo chmod -R 755 /var/www

Lastly, now run your daphne web service to start serving our Django project.

1
daphne -b 172.104.190.249 -p 8000 dev.asgi:application

After executing the command above, you’re expecting to display this information from your web console.

1
2
3
4
2018-12-02 03:24:24,831 INFO     Starting server at tcp:port=8000:interface=1729
2018-12-02 03:24:24,833 INFO     HTTP/2 support not enabled (install the http2 )
2018-12-02 03:24:24,834 INFO     Configuring endpoint tcp:port=8000:interface=19
2018-12-02 03:24:24,837 INFO     Listening on TCP address 172.104.190.249:8000

Finally, access the “Hello World!” page here.

You can download the source code from our GitHub repositories at https://github.com/pinoylearnpython/dev and stay tuned for any updates.

In the next event loop on {{ PLP }}.

Congratulations!, if you can see the Hello World! page, I’m happy for you and you’ve learned a lot in our today’s event loop.  For those who’re not able to successfully launch your Hello World page, don’t worry, leave a comment below and I’m happy to help you to succeed.

Up next, we will be discussing on How to Install MySQL and phpMyAdmin on Ubuntu 18.04 with NGINX web server.   This is in preparation for the CRUD (Create, Read, Update, and Delete) database operations in Django framework for Python 3.6+.

That’s all, have fun learning with {{ PLP }}.

To help Filipino students to learn Python programming language with Django to enhance their capabilities in developing robust web-based applications with practical and direct to the point tutorials, step-by-step with actual information that I provided for you. Leave a comment below or email me at [email protected], thank you!