How To Create a Flask Web Application With Postgresql
### Prerequisites
- Ubuntu 18.04
- Python3
- pip3
### Steps
- Install Postgresql & Create database user and the database
- Create Python virtual environment
- Install Flask and other required modules
- Create codebase
- Run database migration
- Run the Flask application
### Install Postgresql & Create Database
- Run following command in terminal to install postgresql
sudo apt-get install postgresql postgresql-contrib - To verify installation, run the command:
sudo -u postgres psql -c "SELECT version();" - Create User and DB
sudo su - postgres -c "createuser devopsuser"
sudo su - postgres -c "createdb devopsdb" - Grant privileges
sudo -u postgres psql
grant all privileges on database devopsdb to devopsuser;
alter user devopsuser with password 'devops';
run following to exit from psql
\q - Enable remote access to postgresql, edit
sudo vi /etc/postgresql/10/main/postgresql.conf
Change the line "listen_addresses = 'localhost'" to "listen_addresses = '*'"
Save and exit the file
Restart postgresql
sudo /etc/init.d/postgresql restart
### Create python virtual environment
- Create a directory "python-flask-pg"
- cd python-flask-pg
- pip3 install virtualenv
- cd python-flask-pg
- virtualenv env
- Activate virtualenv with command and keep it activated for rest of the work.
- source env/bin/activate
### Install Flask and other required modules
- Create a file requirement.txt and put following dependencies in it. Make sure the virtual env is activated.
Flask
flask_sqlalchemy
flask_script
flask_migrate
psycopg2-binary - Install above dependencies using following command
pip3 install -r requirement.txt
### Create .env with the following code
Run the following command to make these variable available to the current shell:
source .env
source .env
export APP_SETTINGS="config.DevelopmentConfig" export DATABASE_URL="postgresql://devopsuser:devops@localhost/devopsdb"
### Create app.py with the following code
from flask import Flask, request, jsonify, render_template from flask_sqlalchemy import SQLAlchemy import os app = Flask(__name__) app.config.from_object(os.environ['APP_SETTINGS']) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) from models import Employee @app.route("/") def hello(): return "Hello DevOps!" @app.route("/name/<name>") def get_employee_name(name): return "name : {}".format(name) @app.route("/details") def get_employee_details(): age=request.args.get('age') address=request.args.get('address') return "Age : {}, Address: {}".format(age,address) @app.route("/add") def add_employee(): name=request.args.get('name') age=request.args.get('age') address=request.args.get('address') try: employee=Employee( name=name, age=age, address=address ) db.session.add(employee) db.session.commit() return "Employee added. employee id={}".format(employee.id) except Exception as e: return(str(e)) @app.route("/add/form",methods=['GET', 'POST']) def add_employee_form(): if request.method == 'POST': name=request.form.get('name') age=request.form.get('age') address=request.form.get('address') try: employee=Employee( name=name, age=age, address=address ) db.session.add(employee) db.session.commit() return "Employee added. employee id={}".format(employee.id) except Exception as e: return(str(e)) return render_template("getdata.html") @app.route("/getall") def get_all(): try: employees=Employee.query.all() return jsonify([e.serialize() for e in employees]) except Exception as e: return(str(e)) @app.route("/get/<id_>") def get_by_id(id_): try: employee=Employee.query.filter_by(id=id_).first() return jsonify(book.serialize()) except Exception as e: return(str(e)) if __name__ == '__main__': app.run()
### Create config.py with the following code
import os basedir = os.path.abspath(os.path.dirname(__file__)) class Config(object): DEBUG = False TESTING = False CSRF_ENABLED = True SECRET_KEY = 'this-really-needs-to-be-changed' SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL'] class ProductionConfig(Config): DEBUG = False class StagingConfig(Config): DEVELOPMENT = True DEBUG = True class DevelopmentConfig(Config): DEVELOPMENT = True DEBUG = True class TestingConfig(Config): TESTING = True
### Create models.py with the following code
from flask_sqlalchemy import SQLAlchemy
from app import db class Employee(db.Model): __tablename__ = 'employee' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String()) age = db.Column(db.String()) address = db.Column(db.String()) def __init__(self, name, age, address): self.name = name self.age = age self.address = address def __repr__(self): return '<id {}>'.format(self.id) def serialize(self): return { 'id': self.id, 'name': self.name, 'age': self.age, 'address':self.address }
### Create manage.py with the following code
from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from app import app, db migrate = Migrate(app, db) manager = Manager(app) manager.add_command('db', MigrateCommand) if __name__ == '__main__': manager.run()
### Create getdata.html inside templates directory with the following code
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> </head> <body> <div class="container"> <div class="container"> <br> <br> <div class="row align-items-center justify-content-center"> <h1>Add an employee</h1> </div> <br> <form method="POST"> <label for="name">Employee Name</label> <div class="form-row"> <input class="form-control" type="text" placeholder="Name of Employee" id="name" name="name"> </div> <br> <div class="form-row"> <label for="author">Age</label> <input class="form-control" type="text" placeholder="Employee Age" id="age" name="age"> </div> <br> <div class="form-row "> <label for="published">Address</label> <input class="form-control " type="text" placeholder="Address" id="address" name="address"> </div> <br> <button type="submit " class="btn btn-primary " style="float:right ">Save</button> </form> <br><br> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js " integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo " crossorigin="anonymous "></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js " integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49 " crossorigin="anonymous "></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js " integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy " crossorigin="anonymous "></script> </body> </html>
### Database Migration
- flask_sqlalchemy is needed for database migrations which we have already installed above with requirements.txt or you can install it with below command as well
pip3 install flask_sqlchemy - python3 manage.py db init
- python3 manage.py db migrate
- python3 manage.py db upgrade
- Above commands will create the schema in database
### Running the App
- Run the following command from the root of project directory
- python3 manage.py runserver
- Now Open the browser and hit the url - localhost:5000
- Access http://localhost:5000/add/form in browser to see the form to save data
- Access http://localhost:5000/getall to see all the data
Yes, indeed. There is no reason to doubt the validity of this view. Many technologies have already applied this idea at least once. So, for the next promotional event if the company is looking for smart but impressive gifts, then promtional pen
ReplyDeletecan be a reliable proposal. This is also economical, the most important part of your budget will be saved.