So far, we have only a blank homepage, and we do not have anything to put on this page. So, we need to build an admin page or a dashboard to create posts to populate this page. But, as the dashboard is a restricted area, we need to build a login page first to authenticate user before letting them get into this area.

 

In web programming, the MVC (Models, Views, Controllers) pattern is the most adopted by web developers. For our web application, we can follow this pattern too.

 

We have been already creating views folder since the beginning, we need only to add controllers and models folders to follow the MVC pattern.

 

Moreover, we can code login mechanism as a separated application or a blueprint to be mounted with the main application in the entry point index.py file.

 

from bottle import static_file, get
from routes.frontend import index
from routes.frontend import login


app = index.app
app.mount('/login', login.app)

@app.get('/static/<filepath:path>')
def staticFile(filepath):
    return static_file(filepath, root="public")


###################################################################
import socket
host = socket.getfqdn()    
addr = socket.gethostbyname(host)
if(addr == '127.0.1.1'):
    app.run(host='localhost', port=8000, debug=True, reloader=True)

###################################################################

 

# routes/frontend/login.py

from bottle import Bottle, get, post
from controllers.frontend.login import Login


app = Bottle()
login = Login()

@app.get("/")
def getLogin():
    return login.getPage()

 

# controllers/frontend/getPage.py

import config, copy
from bottle import template


class Login:
    def __init__(self):
        settings = copy.deepcopy(config.settings)
        self.setup = settings()

    def getPage(self):
        self.setup["pageTitle"] = "Log into Admin Page"
        self.setup["route"] = "/login"

        return template("base", data=self.setup)

 

<!--views/frontend/login.tpl-->

<link rel="stylesheet" href="/static/styles/frontend/login.css" />

<section class="Login">
    <div class="outer region">
        <div class="title">{{ data["pageTitle"] }}</div>
        <form action="/login" method="post">
            <a>Email:</a><input type="email" name="email" />
            <a>Password:</a><input type="password" name="password" />
            <a></a><input type="submit" value="Submit" />
            <a></a><div class="message">{{ data["message"] }}</div>
        </form>
    </div>
</section>

 

<!--views/base.tpl-->

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        <title>{{ data["siteTitle"] }} | {{ data["pageTitle"] }}</title>
        <script src="/static/scripts/jquery.js"></script>
        <link href="/static/images/sitelogo.png" rel="icon" />
        <link href="/static/fonts/setup.css" rel="stylesheet" />
        <link href="/static/styles/base.css" rel="stylesheet" />
    </head>
    <body>
        <%  
        if(data["route"] == "/login"):
            include('./frontend/login.tpl')
        end
        %>
    </body>
</html>

 

/* public/styles/frontend/login.css */

.Login .outer{
    margin-top: 100px;
    width: 400px;
    background-color: var(--background);
}

.Login .outer .title{
    text-align: center;
    border-bottom: 1px solid var(--background-light);
    font: 25px/1.5 BlackOpsOne;
}

.Login .outer form{
    display: grid;
    grid-template-columns: 20% auto;
    grid-gap: 5px;
    padding: 20px;
    align-items: center;
}

.Login .outer form input{
    font: var(--body-font);
    padding: 1px 5px;
}

.Login .outer form a{
    text-align: right;
    color: white;
}

.Login .outer form .message{
    text-align: center;
}

 

GitHub: https://github.com/Sokhavuth/TV-Channel 

Vercel: https://khmerweb-tv-channel.vercel.app/login