Minibase_Readme ======================== # Introduction Minibase is a management tool for companies that need a high flexibility and manage interlaced projects. In this Readme I will focus on the entry point and the structure of the main application. For more detailed information of each part you will find a separated Readme in each *module* *template* *Static* files etc... **Hope You enjow it** # Knowledge required to deploy Minibase The list can be scary for but if you don't want to make some changes, some basic python and web knowlegde would de sufficient. - [Python](https://www.python.org/) - [Flask](https://flask.palletsprojects.com/en/3.0.x/) - [flask-sqlalchemy](https://flask-sqlalchemy.palletsprojects.com/en/3.1.x/) - [flask-wtf](https://flask-wtf.readthedocs.io/en/1.2.x/) - [flask-session](https://flask-session.readthedocs.io/en/latest/) - [flask-bcrypt](https://flask-bcrypt.readthedocs.io/en/1.0.1/) - [flask-login](https://flask-login.readthedocs.io/en/latest/) - [flask-mail](https://flask-mail.readthedocs.io/en/latest/) - [flask-migrate](https://flask-migrate.readthedocs.io/en/latest/) - [f] - [Sql](https://en.wikipedia.org/wiki/SQL) - [Postgres](https://www.postgresql.org/) - [Docker](https://www.docker.com/)(Otpional) - [Dockefile](https://docs.docker.com/guides/workshop/02_our_app/) - [Docker-compose](https://docs.docker.com/compose/gettingstarted/) - [Traefik](https://traefik.io/traefik/) - [HTML](https://www.w3schools.com/html/) - [CSS](https://www.w3schools.com/css/) - [Bootsrap](https://getbootstrap.com/docs/5.3/getting-started/introduction/) # The struture The main overwiev how the file structure is organised. This Flask Application is using [Blueprints](https://flask.palletsprojects.com/en/3.0.x/blueprints/) for modularity purposes. In odrder to not overencoumber this docuemntation I will isolate each blueprint and the main app. ```Bash inibase/ ├── docker-compose.yml "Docker compose file to start create an start the container"(optinal) ├── LICENSE ├── README.md └── web ├── run.py "Entry point to the app ->" `python3 run.py` ├── Dockerfile "Docker file to containerize the application"(optinal) ├── requirments.txt "Python requirement." └── minibase "Main App folder" ├── app.py "Main application called by" `../run.py` ├── config.py "Configurarion for Flask" ├── theme.py "My approach to make a semi interractive color sheme and navbar menus" ├── blueprints "Main Blueprint folder" │ └── <Blueprint_Name> "Blueprint folder -> named as you like" │ ├── forms.py "Definition of the forms to be used for the blueprint" │ ├── models.py "Database models" │ ├── routes.py "Routes for the html files and interractions for them" │ ├── utils.py "Every Bluprint has it's functionalities coded here" │ └── templates "Template folder for the current blueprint" │ └── <Blueprint_Name> "Same as the blueprint name (this is a naming convention)" │ └── <template>.html "Names of the HTML templates for this Blueprint" ├── static "Default location for Static files for the app" │ ├── css "Here will be the CSS for Bootstrap and your own" │ ├── img "Images as logos and icons" │ ├── js "Here will be the JS for Bootstrap and your own" │ └── pics "Pictures for users avatars etc.." └── templates "Main Templates folder : for the entire app, Ex: base.html is here" └── <template>.html "Names of the HTML templates for main app" ``` # The Entry point and the main App ## Building the virtual enviroment and running the app I would make sense to start from the [benninging](https://www.youtube.com/watch?v=vacJSHN4ZmY)! so we are int he *minibase/web/* directory and working with *run.py* is our entry point and the one which will call *minibase/app.py*. - To Sart you need to create a Python *virtual envirement* and *activate it* -> [Instructions](https://git.keydev.me/Kerem/miniBase/src/branch/master/.trainings/flask_to_docker/README.md#create-a-python-virtual-enviroement) - There is nothing special going on on the code, just *creating* and *running* the application -> [Instructions](https://git.keydev.me/Kerem/miniBase/src/branch/master/.trainings/flask_to_docker/README.md#the-main-funtion-to-start-a-flask-server) - PLease note that it still runs in debug `debug=True` enviroment so please be careful if you are wiling to open it to the WWW. ```python from minibase.app import create_app # Creation of the main app flask_app = create_app() # Running ht main app the flask app is configured at app.py with an external config.py file if __name__ == '__main__': flask_app.run(debug=True) ``` ## Main Application and initialisation Here is where the magic starts, all the *Blueprints* and [Modules](https://docs.python.org/3/tutorial/modules.html) comes together the form the main application. We will habve a look a *app.py*, *config.py* and *theme.py*. we Dont need any initial steps as they are taken care of from *run.py* ### *app.py* - Modules for the modules used here please refer to the links liusted at th beginning. ```Python from flask import Flask from flask_session import Session from flask_sqlalchemy import SQLAlchemy from flask_bcrypt import Bcrypt from flask_login import LoginManager from flask_mail import Mail from flask_migrate import Migrate from minibase.config import AppConfig ``` - Global declarations Code comments should suffice. In othe case write to me ;) ```python # (DATABASE) Definition db = SQLAlchemy() # (PASSWORD) Hashing Module to save paswords safely bcrypt = Bcrypt() # (LOGIN) Login manage plugin configuration login_manager = LoginManager() login_manager.login_view = 'users.login' # User management (current_user) login_manager.login_message_category = 'info' # Boostrap Info Message # (EMAIL AGENT) Definition mail = Mail() # So that we can send mails # (SESSION) Starts the curren flask session session = Session() ``` - Definition and initialisation of the *app*. ```python def create_app(): # (APP) Definition app = Flask(__name__) # (APP) Configure configuration app.config.from_object(AppConfig) # (DATABASE) Initialisation db.init_app(app) # (PASSWORD) Initialisation bcrypt.init_app(app) # (LOGIN) Initialisation login_manager.init_app(app) # (EMAIL AGENT) Initialisation mail.init_app(app) # Session for variable manipulation on server side # (DATABASE) Linking the app and the Database Migrate(app, db) ``` - *Blueprints* being imported and registered. We will go deeper in Bluprints Afterward - **_NOTE:_** This is not an exaustive list of *Blueprints* just some exmaples to make it more understandable. ```python # (BLUEPRINTS) Importing the blueprints. # Include are made here to awoid the Circular import issues from minibase.blueprints.main.routes import main from minibase.blueprints.user.routes import user from minibase.blueprints.errors.routes import errors # (BLUEPRINTS) Registering the blueprints. # Giving them theie ulr_prefixes that will define their links on the webBrowser. app.register_blueprint(main, url_prefix='/') app.register_blueprint(user, url_prefix='/user') app.register_blueprint(errors, url_prefix='/errors') # (APP) Returning the initialised app return app ``` # Main Templates Here you will find the what i call the Main *templates*, what do i mean by that ? - Flask allows us to work with [templates](https://flask.palletsprojects.com/en/3.0.x/tutorial/templates/) which are *HTML* files, in combination with [Jinja2](https://jinja.palletsprojects.com/en/3.1.x/templates/) template engine - This means we can use some *Python* code in out *HTML* - The most common practice is to define a *Base template* which defines the parts of our website that will stay the same. like the nav bar footer etc... - have called it *base.html* Let's have a look and i guess you will understand it better ## Base template So as this is the *base* *template* which every other template *will* [extend](https://flask.palletsprojects.com/en/2.3.x/patterns/templateinheritance/) from, i have overly commented it. - `{# #}` are *Jinja* *Comments* and are *not visible* at the website source code - `<!-- --!>` are *HTML* *Comments* and are *visible* at the website source code ### base.html - Here you can already see some interesting use of *Jinja* - To add a Variable we use `{{ <varible> }}` - To add a loop of a comparison we use : `{% <statement> %}` - The rest is Standart [HTML](https://www.w3schools.com/html/) - So what is going on here : - `<head>` we define the *HTML* propoerties an reference our [CSS](https://www.w3schools.com/css/) *stylesheets* - `<title>{% block title %}Minibase{% endblock %}</title>` We define the *title* with a *default* value | which will be *overwritten* if another html file has a `<{% block title %}{% endblock %}` block - `<body style="{{ theme.maineTheme.div_style }}"> ` Here is a an example of how to use *Varible* in *HTLM*. Here I define the `<body style=` with a *varibale* tha is *declared* in *theme.py*. - ` {% with messages = get_flashed_messages(with_categories=true) %}` Here we do a check everytime that *base.html* is loaded to see if there is any *messages* to [Flash](https://flask.palletsprojects.com/en/2.3.x/patterns/flashing/). and *show* them *dynamically* wiht their appropriate *categories*. We will also see som examples in the future don't worry. - `{% block content %} {% endblock %}` Same as for the title content there here will be *inserted* the *content* of each *template* ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no"> <!-- Referencing custom CSS stylesheet --!> <link rel="stylesheet" type="text/css" href="/css/style.css"/> <!-- Referencing Bootstrap CSS stylesheet --!> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> <!-- Referencing Favicon --!> <link rel="shortcut icon" href="{{ url_for('static', filename='img/logo.png') }}"> {# Title Block : wit Minibase as defauls value : will be overwritten if anothe page has the same title block #} <title>{% block title %}Minibase{% endblock %}</title> </head> {# Here You can see how we use variables in HTML code #} <body style="{{ theme.maineTheme.div_style }}"> {# We can also include othe html files #} {% include 'navbar.html' %} <main> {# This part will catch anny messages that we want to FLASH when something has been updated #} {# Gets the messages with their respective categories #} {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {# If there are messages present #} {% for category, message in messages %} {# Get the message and his category #} <div class="alert alert-{{ category }}"> {{ message }} {# Print it #} </div> {% endfor %} {% endif %} {% endwith %} {% block content %} {# Every extra template will be placed here for examplem login.htlm and so on #} {% endblock %} </main> <!-- Incluting the scrips for bootstrap | Bootstrap 5 don't need jquery anymore --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script> {% block scripts %}{% endblock %} </body> </html> {# These are Jinja comments and will not be shown if someone was to look at the source code of this page contrary to the HTML comments#} ```