• Get application security done the right way! Detect, Protect, Monitor, Accelerate, and more…
  • Let’s learn how to expose a Django demo app to the internet. That, without deploying it in a hosting service.

    Configuring a staging deployment environment just to show a demo of your Django app is awful. Even more, if you only need a URL for a couple of minutes, to show it up to a client or teammate.

    The best option is to use a tool to expose your current local server. Exactly! People all around the world will be able to see what’s happening on your localhost.

    For that purpose, we will use Ngrok. This tool will allow us to create public URLs based on the local ports of our computers. All of this thanks to the magic of Tunnels.

    Before starting all the code worked on this tutorial, will be available in this Github repository.

    Pre-requirements

    It’s recommended to know all these basic things. Although it’s probable you can follow along with this tutorial, without further problems.

    Creating a Django app

    In order to create a step-by-step tutorial, I’ll explain the process of creating a Django project. If you already have one, you can skip this section.

    Virtual environment

    First of all, let’s create a Python virtual environment.

    • So open up your system terminal (or shell).
    • If you find it too complicated to open your system terminal, try to use the built-in terminal of the code editor.

    • Click on Terminal>New terminal, and a shell should appear at the bottom of your screen.
    • Type the following command to create a virtual environment, with the built-in Python tool.
    python -m venv .venv

    It basically means:

    Hey Python, create a virtual environment (-m venv) command with the name of .venv 

    • Now if you list the files of your current directory, you should see a .venv folder.
    $ ls -l
    drwxr-xr-x    - daniel 30 abr 23:12 .venv
    # Other files ...
    • To activate the virtual environment, we call the source command.
    source .venv/bin/activate
    • If you find any trouble, please refer to the following table extracted from the official python documentation.
    Platform Shell Command to activate virtual environment
    POSIX bash/zsh $ source <venv>/bin/activate
    fish $ source <venv>/bin/activate.fish
    csh/tcsh $ source <venv>/bin/activate.csh
    PowerShell Core $ <venv>/bin/Activate.ps1
    Windows cmd.exe C:\> <venv>\Scripts\activate.bat
    PowerShell PS C:\> <venv>\Scripts\Activate.ps1

    Now if you have run the correct command, your shell should have the name of the virtual environment in it.

    $ source .venv/bin/activate.fish
    
    (.venv) $ 
    

    Install Django

    After activating your virtual environment, now you are able to install whatever Django version you want. In this case, it’s a good choice to install the latest.

    $ pip install django
    Collecting django
      Using cached Django-3.2-py3-none-any.whl (7.9 MB)
    Collecting pytz
      Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB)
    Collecting asgiref<4,>=3.3.2
      Using cached asgiref-3.3.4-py3-none-any.whl (22 kB)
    Collecting sqlparse>=0.2.2
      Using cached sqlparse-0.4.1-py3-none-any.whl (42 kB)
    Installing collected packages: pytz, asgiref, sqlparse, django
    Successfully installed asgiref-3.3.4 django-3.2 pytz-2021.1 sqlparse-0.4.1
    

    Now it’s time to create the basic project structure of the Django app you want to expose.

    $ django-admin startproject mytestingproject
    

    This will create a Django project with the name of mytestingproject. After creating it we want you will want to enter the directory where the project structure is located. So let’s cd into it and run the Django server.

    # Enter to the project directory
    (.venv)$ cd mytestingproject/
    
    # Listing the files inside the project
    (.venv) $ ls
    mytestingproject  manage.py 

    Now that you are in, let’s run the Django server to see how it looks.

     (.venv) $python manage.py runserver
    Watching for file changes with StatReloader
    Performing system checks...
    
    System check identified no issues (0 silenced).
    
    You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
    Run 'python manage.py migrate' to apply them.
    May 01, 2021 - 04:34:25
    Django version 3.2, using settings 'mytestingproject.settings'
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CONTROL-C.
    

    Basically, Django is telling us that a local server is running at our localhost (127.0.0.1 always points to it), on the default port, 8000.

    Don’t worry about the error message. First, let’s check all is working fine on our local server. To do that, go to your web browser and paste this direction:

    http://localhost:8000/
    # Do you note that localhost and 127.0.0.1 are the same?

    If everything is working fine, you should see a Django beautiful template.

    That’s all about our Django installation.

    Now let’s get into exposing this Django project. If you are working on a more complex project, the following methods of exposing Django apps also will work.

    Exposing a Django app with Ngrok

    As I said before Ngrok is one of the tools that will let us land our local server on the internet. So first of all Download Ngrok from the official website.

    Once you have installed it, let’s proceed with the needed commands.

    Open another shell, keeping the terminal your Django server is currently running, and type.

    $  ngrok help
    NAME:
       ngrok - tunnel local ports to public URLs and inspect traffic
    
    More commands ....

    This will give you a quick look at the available commands that Ngrok offers, and also will grant that the installation process went correctly.

    In order to create a URL where people can access our server, let’s run.

        $ ngrok http 8000 
    # secure public URL for port 8000 web server
    

    We are running the http argument, to create an URL that will connect to port 8000 of our localhost.

    Here is the result you’ll probably get.

    ngrok by @inconshreveable                                                                      (Ctrl+C to quit)
                                                                                                                   
    Session Status                online                                                                           
    Session Expires               1 hour, 59 minutes                                                               
    Update                        update available (version 2.3.39, Ctrl-U to update)                              
    Version                       2.3.35                                                                           
    Region                        United States (us)                                                               
    Web Interface                 http://127.0.0.1:4040                                                            
    Forwarding                    http://cac2165aa7f8.ngrok.io -> http://localhost:8000                            
    Forwarding                    https://cac2165aa7f8.ngrok.io -> http://localhost:8000                           
                                                                                                                   
    Connections                   ttl     opn     rt1     rt5     p50     p90                                      
                                  0       0       0.00    0.00    0.00    0.00       

    As it says, Ngrok is forwarding that weird and ugly URL, to our localhost. But the magic happens, when you hit the browser with the URL Ngrok gave you.

    Error page.

    Changing settings.py

    Wow, what just happened 😱?

    It seems Django is throwing an error because of a DisallowedHost setting. If you check the shell you are running the Django server in, and the one with the Ngrok session, you’ll get some debug messages.

    # Django messages
    Invalid HTTP_HOST header: 'cac2165aa7f8.ngrok.io'. You may need to add 'cac2165aa7f8.ngrok.io' to ALLOWED_HOSTS.
    Bad Request: /
    [01/May/2021 05:07:46] "GET / HTTP/1.1" 400 65196
    Invalid HTTP_HOST header: 'cac2165aa7f8.ngrok.io'. You may need to add 'cac2165aa7f8.ngrok.io' to ALLOWED_HOSTS.
    
    # Ngrok messages
    HTTP Requests                                                            
    -------------                                                            
                                                                             
    GET /favicon.ico               400 Bad Request                           
    GET /                          400 Bad Request                           
                                                  

    As Django is telling us, we must add the domain we are connecting to the ALLOWED_HOSTS config variable. But we have a problem, and it is that the domain name is too large and confusing.

    So let’s change a little bit the Django settings, to solve this error. Open the settings.py file located in the project folder.

    # mytestingproject/settings.py
    
    # Line 28
    
    # Change from
    ALLOWED_HOSTS = []
    
    # To
    
    ALLOWED_HOSTS = ["*"]

    If you know some regex, you can appreciate that we’re setting a wildcard, where all the hosts will be allowed.

    Now reload the site, and see the result.

    Working page

    All is working perfectly now! And if you start to create applications for the project and setting URLs and views, all will be reflected on that public URL.

    Note: Don’t forget to change ALLOWED_HOSTS in production, since it would produce a huge security hole.

    Conclusions

    In this tutorial, you learned how to create a demo URL for your Django project, without the need of deploying it.

    You practiced how to start a Django project and work with the settings.py file in Django.

    Finally, you learned how to use Ngrok, and how to expose any local server with it.

    Next, explore some of the popular Python frameworks to build API.