Web3 backend and smart contract development for Python developers part 8: Django backend (login and logout functionality)
Tags: python, ethereum, nft, backend
Published: 2023-10-03 20:04:07


Now we will move to Django backend part. First step as always is to activate proper Python virtual enviroment. From `./musical_nft_thumbnails` folder 

 `   $source env/bin/activate`


What we need at this point is landing page. Login, logout, sign-up functionality as well as reset password. Ones user sign-up and login into our platform we will redirect him/her to his personal page. There he will be able to see personal information, NFTs he own, buy new with crypto or credit card.  

From root folder create new Django app `authentication`

    $py manage.py startapp authentication

In this newly created app we will manage sign-in process, login, logout and reset password. 

Add to `musical_nft/settings.py` `authentication` to list of installed apps:

```
    INSTALLED_APPS = [
        "django.contrib.admin",
        "django.contrib.auth",
        "django.contrib.contenttypes",
        "django.contrib.sessions",
        "django.contrib.messages",
        "django.contrib.staticfiles",
        # here =>
        "authentication",
]
```


Now in global `urls.py` inside `musical_nft/settings.py` add 

   

```
 from django.contrib import admin
    from django.urls import path, include

    urlpatterns = [
        path("admin/", admin.site.urls),
        path("", include("authentication.urls"))
    ]
```

Now all `path` we have inside authentication app will be pluged to this project `urls.py`

In authentication app folder create another `urls.py` and pass following code

 

```
   from django.urls import path
    from .views import HomeView

    urlpatterns = [
        path("", HomeView.as_view(), name="home"),
    ]
```


If you didn't create super user lets do it now

    $python manage.py createsuperuser

Now open browser `http:127.0.0.1:8000/admin` while local Django server running and type superuser credentials (always make sure your postgres server is up and running `$sudo service postgresql start`). 


![Image description ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j30gzl0by2akqcbh0n15.png)


Ones you are logged in go to user and add new user (confirm password)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bma5py7k9bq9wt4sb44c.png)


At this point we need `authentication` view class and few html page to be rendered. Have on mind when you create Django apps that it is always 3 step process: defining urls (in app), views (in our case class based view. It can easly be function based view if you like to experiment with alternative implementations of this code) and templates (html page to be rendered with few added Django elements). 


Inside `views.py` file of `authentication` app add following code:


    

```
from django.shortcuts import render
    from django.views.generic import TemplateView

    class HomeView(TemplateView):

        def get(self, request):
            return render(request, "home.html", {})
```
                

Only for test purpose lets make simple `home.html` file with message to be displayed in browser. For this to happen create in `./muscial_nft_thumbnails/tempaltes/home.html`

    
   

```
 {% extends "base.html" %}

    {% block content%}
        <h1> Test screen </h1>
    {% endblock content%}
```


This peculiar curly brackets above are part Django syntax we need to use with our templates

Then in `settings.py` define root of `template` folder

    

```
TEMPLATES = [
        {
            "BACKEND": "django.template.backends.django.DjangoTemplates",
            "DIRS": [os.path.join(BASE_DIR, "templates")],
            "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",
                ],
            },
        },
    ]
```



In this project we will use [bootstrap](https://getbootstrap.com/) for styling. Go on their documentation page and pick up from `introduction` second option number two, `Include Bootstrap’s CSS and JS.` and pass that code in newly created `base.html` inside project root `./templates` folder (or you can simply copy from here)

    

```
<!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Muscial NFT</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
    </head>
    <body>
        <div class="container ">       
            <br/>
            <br/>
            {% block content %}
            {% endblock content %}
        </div>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
    </body>
    </html>
```


Now add `navbar` to our `base.hmtl` page. 

We can do this again over `bootstrap` site documentation, search  for `navbar` in `components`. Choose one you like the most. For our demostration purpose first will be ok. 

Here is edited code that you need to pass to `navbar.html` file inside `./templates` folder in project root directoy. 


    

```
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container-fluid">
        <a class="navbar-brand" href="{% url 'home' %}">Musical NFT </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
                <a class="nav-link" href="#">Link</a>
            </li>
                </ul>
            </li>
            </ul>
        </div>
        </div>
    </nav>
```

And then just go to previously created `base.html` and add one new line bellow first body tag
`
        {% include "navbar.html"%}`


From root directory 

   ` $py manage.py runserver`
    
Go to browser to `http://127.0.0.1:8000` and check if you get proper message displayed

Now if you go back to you browser you should see somethin like this


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/95po8ydnchwdpigdh521.png)

Ones we have this we can move and add some basic sign-in, login, logout and reset password functionality. For login and logout we will use Django authentication system. 


Here is general overview on how we plan to plug all things together related to authetication 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87n9oiuq0t6vukbodhda.png)

First we will further develop 3 basic templates: `navbar`, `base` and `home` (`base` includes `navbar` and `home` extends `base` as flow shows). We should have on mind that `home` will have two possbilities: 1) if user is logged we will show to him his personal page; 2) If user is not logged we will offer  him login forms (you can check this in `home.html`). 

`navbar.html` (modified bootstrap navbar)


    

```
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container-fluid">
        <a class="navbar-brand" href="{% url 'home' %}">Musical NFT </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            {% if user.is_authenticated%}
            <li class="nav-item">
            <a class="nav-link" href="{% url 'logout'%}">Logout</a>
            </li>
            {% else %}
            <li class="nav-item">
            <a class="nav-link" href="{% url 'home'%}">Login</a>
            </li>
            {% endif%}
                </ul>
            </li>
            </ul>
        </div>
        </div>
    </nav>

```

Now `base.html` to include `navbar.html`

    

```
<!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Muscial NFT</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
    </head>
    <body>
        {% include "navbar.html"%}
        <div class="container ">       
            <br/>
            <br/>
            {% if messages %}
            {% for message in messages%}
            <div class="alert alert-warning alert-dismissible fade show" role="alert">
            {{ message }}
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
            </div>

            {% endfor%}
            {% endif %}

            {% block content %}
            
            {% endblock content %}
        </div>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
    </body>
    </html>
```

Here I want to draw your attention on last `{% block content %}` `{% endblock content %}` This is place where `base.html` injects any other template that inheriti from him with `extends`command (in our case `home.html`) 

Then few lines above you have a bit strange syntax with `{% if messages %} {% for message in messages%}` Simply this is the way we pass to our template success error message. You will find more details about this in `view.py`.

As we see `home.html` will extend `base.html` and have inside itself Django specific `if/else` statemnt. This `if/else` statment will help us check if user is logged in, then we will offer to him his persoanl page. In case he is not logged in we will show login form. 

Here is code example: 

   

```
 {% extends "base.html" %}

    {% block content%}

    <div class="col-md-6 offset-md-3"> 

        {% if user.is_authenticated %} 
        <h1> Welcome <h1/>
        {% else %}
        <h1> Login </h1>
        <br/>
        <form method="POST" action="{% url 'home' %}"> 
            {% csrf_token %}
            <form>
                <div class="mb-3">
                <input type="text" class="form-control" aria-describedby="emailHelp" placeholder="Username" name="username" required>
                </div>
                <div class="mb-3">
                <input type="password" class="form-control" placeholder="Password" name="password" required>
                </div>
                <button type="submit" class="btn btn-secondary">Submit</button>
            </form>
            </form> 
    </div>

    {% endif %}
    {% endblock content%}

```

Now we have all templates and we can finally move to authentication app folder where we need to update our `urls.py` with following code

```
    from django.urls import path
    from .views import HomeView, LogoutUser

    urlpatterns = [
        path("", HomeView.as_view(), name="home"),
        # path("login/", LoginUser.as_view(), name="login"),
        path("logout/", LogoutUser.as_view(), name="logout"),
    ]
```

As you can see we added new logout path (login is part of normal `home` path and `HomeView` class) which will be handled with `LogoutUser` class inside authenticaiotn `view.py`

As you may guess last piece of puzzle we need now is `view` handler which will glue all this elements together. Here is example of possbile code: 

    

```
from django.shortcuts import render, redirect
from django.views.generic import TemplateView
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages


class HomeView(TemplateView):
    template_name="home.html"

    def post(self, request):
            # check to see if loggin in
            user_name = request.POST["username"]
            password = request.POST["password"]
            user = authenticate(request, username=user_name, password=password)
            if user is not None:
                login(request, user)
                messages.success(request, "You have been logged in!")
                return redirect("home")    
            else:
                messages.success(request, "There was An Error login in, please try again")
                return redirect("home")  
        
    def get(self, request):
        return render(request, "home.html", {})            

    class LogoutUser(TemplateView):    
        def get(self, request):
            logout(request)
            messages.success(request, "You have been logged out!")
            return redirect("home")  

```
In this moment run your Django server locally (be sure again your postgres server is up and runnig) and then go to `http://127.0.0.1:8000` If you are logged out as admin, you should see something like this


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9trpf1oc5ag7r87oal6l.png)

Now type admin or newly created user credentials and you should see something like this =>

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nvdn42rorgt57152qx36.png)


Look at upper left corner of `navbar` logout button. This button will hit our `logout/` path and then `LogoutUser` class handler (from `views.py`) which will then simply logout current user and redirect him to `home` page. 

And on this point finally we can see very nice moment in `home.html`. This loop inside `home.html` will see that user is not logged in any more and he will show him login format. And basically with this nice detail we have everything in one place: login, logout and user profile all nicely connected thorough this template loop.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mugg7gkbqzuhmtzunupo.png)

Now when we have `login` and `logout` let's move to develop `sign-up` and `reset password` functionality before we start to work on our web3 integration.

Code for this you can find on [github](https://github.com/ilijapet/musical_nft_thumbnails)