article

Showing posts with label Python-Flask. Show all posts
Showing posts with label Python-Flask. Show all posts

Saturday, April 15, 2023

React-JS and Python Flask CRUD Create, Read, Update and Delete MySql-Database

React-JS and Python Flask CRUD Create, Read, Update and Delete MySql-Database

Python Flask 

https://flask.palletsprojects.com/en/2.2.x/installation/
 
Create an environment
C:\flask_dev>py -3 -m venv venv

Activate the environment
C:\flask_dev>venv\Scripts\activate

Install Flask
venv C:\flask_dev>pip install Flask
C:\flask_dev\flaskreact\app.py

Install requirements

Flask-SQLAlchemy
Flask-SQLAlchemy is an extension for Flask that adds support for SQLAlchemy to your application.
https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/

(venv) PS C:\flask_dev\flaskreact>pip install -U Flask-SQLAlchemy

Flask + marshmallow for beautiful APIs
https://pypi.org/project/flask-marshmallow/

(venv) PS C:\flask_dev\flaskreact>pip install flask-marshmallow
(venv) PS C:\flask_dev\flaskreact>pip install Flask-Cors

C:\flask_dev\flaskreact\app.py

#C:\flask_dev\flaskreact\app.py
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
import datetime
from flask_marshmallow import Marshmallow #ModuleNotFoundError: No module named 'flask_marshmallow' = pip install flask-marshmallow https://pypi.org/project/flask-marshmallow/
from flask_cors import CORS #ModuleNotFoundError: No module named 'flask_cors' = pip install Flask-Cors

app = Flask(__name__)
CORS(app)

# Databse configuration                                  Username:password@hostname/databasename
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:''@localhost/flaskreact'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db=SQLAlchemy(app)

ma=Marshmallow(app)

class Users(db.Model):
    __tablename__ = "users"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(100))
    email = db.Column(db.String(100))
    date = db.Column(db.DateTime,default=datetime.datetime.now)

    def __init__(self,name,email):
        self.name=name
        self.email=email


class UserSchema(ma.Schema):
    class Meta:
        fields = ('id','name','email','date')

user_schema = UserSchema()
users_schema = UserSchema(many=True)

@app.route('/listusers',methods =['GET'])
def listusers():
    all_users = Users.query.all()
    results = users_schema.dump(all_users)
    return jsonify(results)

@app.route('/userdetails/<id>',methods =['GET'])
def userdetails(id):
    user = Users.query.get(id)
    return user_schema.jsonify(user)

@app.route('/userupdate/<id>',methods = ['PUT'])
def userupdate(id):
    user = Users.query.get(id)

    name = request.json['name']
    email = request.json['email']

    user.name = name
    user.email = email

    db.session.commit()
    return user_schema.jsonify(user)

@app.route('/userdelete/<id>',methods=['DELETE'])
def userdelete(id):
    user = Users.query.get(id)
    db.session.delete(user)
    db.session.commit()
    return user_schema.jsonify(user)

@app.route('/useradd',methods=['POST'])
def useradd():
    name = request.json['name']
    email = request.json['email']

    users = Users(name,email)
    db.session.add(users)
    db.session.commit()
    return user_schema.jsonify(users)

if __name__=='__main__':
    app.run(debug=True)
Postman
Postman is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs—faster.
https://www.postman.com/

run (venv) C:\flask_dev\flaskreact>flask run

React JS
https://create-react-app.dev/

Create Project
C:\react-js>npx create-react-app myreactdev

Run
C:\react-js\myreactdev> npm start
C:\react-js\myreactdev\src\App.js

//C:\react-js\myreactdev\src\App.js
import React, { } from 'react';
import './App.css';
  
import {BrowserRouter, Routes, Route} from 'react-router-dom';
  
import ListUserPage from "./pages/ListUserPage";
import CreateUser from './pages/CreateUser';
import EditUser from './pages/EditUser';

function App() {
  return (
    <div className="vh-100 gradient-custom">
    <div className="container">
      <h1 className="page-header text-center">React-JS and Python Flask CRUD Create, Read, Update and Delete MySql-Database</h1>
   
      <BrowserRouter>
        <Routes>
            <Route path="/" element={<ListUserPage />} />
            <Route path="/addnewuser" element={<CreateUser />} />
			<Route path="user/:id/edit" element={<EditUser />} />
        </Routes>
      </BrowserRouter>
    </div>
    </div>
  );
}
   
export default App;
Install React Router Dom
https://www.npmjs.com/package/react-router-dom
C:\react-js\myreactdev>npm i react-router-dom --save

Install Axios
https://www.npmjs.com/package/axios
C:\react-js\myreactdev>npm install axios --save

C:\react-js\myreactdev\src\pages\ListUserPage.js
//C:\react-js\myreactdev\src\pages\ListUserPage.js
import React, { useEffect, useState } from "react";
import axios from "axios" //npm install axios --save 
import {Link} from 'react-router-dom';
 
export default function ListUserPage(){
 
    const [users, setUsers] = useState([]);
    useEffect(() => {
        getUsers();
    }, []);
 
    function getUsers() {
        axios.get('http://127.0.0.1:5000/listusers').then(function(response) {
            console.log(response.data);
            setUsers(response.data);
        });
    }
	
    const deleteUser = (id) => {
        axios.delete(`http://127.0.0.1:5000/userdelete/${id}`).then(function(response){
            console.log(response.data);
            getUsers();
        });
		alert("Successfully Deleted");
    }
	
	return (
    <div>
        <div className="container h-100">
            <div className="row h-100">
                <div className="col-12">
                    <p><Link to="/addnewuser" className="btn btn-success">Add New User</Link> </p>
                    <h1>List Users</h1>
					<table class="table table-bordered table-striped">
						<thead>
							<tr>
								<th>#</th>
								<th>Name</th>
								<th>Email</th>
								<th>Date Added</th>
								<th>Actions</th>
							</tr>
						</thead>
						<tbody>
							{users.map((user, key) =>
								<tr key={key}>
									<td>{user.id}</td>
									<td>{user.name}</td>
									<td>{user.email}</td>
									<td>{user.date}</td>
									<td>
										<Link to={`user/${user.id}/edit`} className="btn btn-success" style={{marginRight: "10px"}}>Edit</Link>
										<button onClick={() => deleteUser(user.id)} className="btn btn-danger">Delete</button>
									</td>
								</tr>
							)}
						</tbody>
					</table>
                </div>
            </div>
        </div>
    </div>
  );
}
C:\react-js\myreactdev\src\pages\CreateUser.js
//C:\react-js\myreactdev\src\pages\CreateUser.js
import React, { useState  } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";

export default function CreateUser(){
 
    const navigate = useNavigate();
 
    const [inputs, setInputs] = useState([]);
 
    const handleChange = (event) => {
        const name = event.target.name;
        const value = event.target.value;
        setInputs(values => ({...values, [name]: value}));
    }
    const handleSubmit = (event) => {
        event.preventDefault();
 
        axios.post('http://127.0.0.1:5000/useradd', inputs).then(function(response){
            console.log(response.data);
            navigate('/');
        });
         
    }
	
	return (
    <div>
        <div className="container h-100">
			<div className="row">
				<div className="col-2"></div>
				<div className="col-8">
				<h1>Create user</h1>
				<form onSubmit={handleSubmit}>
					<div className="mb-3">
					  <label>Name</label>
					  <input type="text" className="form-control" name="name" onChange={handleChange} />
					</div>
					<div className="mb-3">
					  <label>Email</label>
					  <input type="text" className="form-control" name="email" onChange={handleChange} />
					</div>   
					<button type="submit" name="add" className="btn btn-primary">Save</button>
				</form>
				</div>
				<div className="col-2"></div>
			</div>
        </div>
    </div>
  );
}
C:\react-js\myreactdev\src\pages\EditUser.js
//C:\react-js\myreactdev\src\pages\EditUser.js
import React, { useState, useEffect  } from "react";
import axios from "axios";
import { useNavigate, useParams } from "react-router-dom";

export default function EditUser(){
 
    const navigate = useNavigate();
 
    const [inputs, setInputs] = useState([]);
 
    const {id} = useParams();
 
    useEffect(() => {
        getUser();
    }, []);
 
    function getUser() {
        axios.get(`http://127.0.0.1:5000/userdetails/${id}`).then(function(response) {
            console.log(response.data);
            setInputs(response.data);
        });
    }
 
    const handleChange = (event) => {
        const name = event.target.name;
        const value = event.target.value;
        setInputs(values => ({...values, [name]: value}));
    }
    const handleSubmit = (event) => {
        event.preventDefault();
 
        axios.put(`http://127.0.0.1:5000/userupdate/${id}`, inputs).then(function(response){
            console.log(response.data);
            navigate('/');
        });
         
    }
	
	return (
    <div>
        <div className="container h-100">
        <div className="row">
            <div className="col-2"></div>
            <div className="col-8">
            <h1>Edit user</h1>
            <form onSubmit={handleSubmit}>
                <div className="mb-3">
                  <label>Name</label>
                  <input type="text" value={inputs.name} className="form-control" name="name" onChange={handleChange} />
                </div>
                <div className="mb-3">
                  <label>Email</label>
                  <input type="text" value={inputs.email} className="form-control" name="email" onChange={handleChange} />
                </div>   
                <button type="submit" name="update" className="btn btn-primary">Save</button>
            </form>
            </div>
            <div className="col-2"></div>
        </div>
        </div>
    </div>
  );
}
Run C:\react-j\myreactdev>npm start
http://localhost:3000/

Friday, April 14, 2023

React and Python Flask Login Register

React and Python Flask Login Register

Python Flask 

https://flask.palletsprojects.com/en/2.2.x/installation/
 
Create an environment
C:\flask_dev>py -3 -m venv venv

Activate the environment
C:\flask_dev>venv\Scripts\activate

Install Flask
venv C:\flask_dev>pip install Flask
C:\flask_dev\flaskreact\app.py
Install requirements
Flask-Bcrypt
Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.
https://pypi.org/project/Flask-Bcrypt/

(venv) PS C:\flask_dev\flaskreact>pip install Flask-Bcrypt

Flask-SQLAlchemy
Flask-SQLAlchemy is an extension for Flask that adds support for SQLAlchemy to your application.
https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/

(venv) PS C:\flask_dev\flaskreact>pip install -U Flask-SQLAlchemy
C:\flask_dev\flaskreact\app.py

C:\flask_dev\flaskreact\app.py
 
#C:\flask_dev\flaskreact\app.py
from flask import Flask, request, jsonify, session
from flask_bcrypt import Bcrypt #pip install Flask-Bcrypt = https://pypi.org/project/Flask-Bcrypt/
from flask_cors import CORS, cross_origin #ModuleNotFoundError: No module named 'flask_cors' = pip install Flask-Cors
from models import db, User

app = Flask(__name__)

app.config['SECRET_KEY'] = 'cairocoders-ednalan'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskdb.db'

SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
 
bcrypt = Bcrypt(app) 
CORS(app, supports_credentials=True)
db.init_app(app)
 
with app.app_context():
    db.create_all()

@app.route("/")
def hello_world():
    return "Hello, World!"

@app.route("/signup", methods=["POST"])
def signup():
    email = request.json["email"]
    password = request.json["password"]

    user_exists = User.query.filter_by(email=email).first() is not None

    if user_exists:
        return jsonify({"error": "Email already exists"}), 409
    
    hashed_password = bcrypt.generate_password_hash(password)
    new_user = User(email=email, password=hashed_password)
    db.session.add(new_user)
    db.session.commit()

    session["user_id"] = new_user.id

    return jsonify({
        "id": new_user.id,
        "email": new_user.email
    })

@app.route("/login", methods=["POST"])
def login_user():
    email = request.json["email"]
    password = request.json["password"]
 
    user = User.query.filter_by(email=email).first()
 
    if user is None:
        return jsonify({"error": "Unauthorized Access"}), 401
 
    if not bcrypt.check_password_hash(user.password, password):
        return jsonify({"error": "Unauthorized"}), 401
     
    session["user_id"] = user.id
 
    return jsonify({
        "id": user.id,
        "email": user.email
    })

if __name__ == "__main__":
    app.run(debug=True)
C:\flask_dev\flaskreact\models.py
 
#C:\flask_dev\flaskreact\models.py
from flask_sqlalchemy import SQLAlchemy
from uuid import uuid4

db = SQLAlchemy()

def get_uuid():
    return uuid4().hex

class User(db.Model):
    __tablename__ = "users"
    id = db.Column(db.String(11), primary_key=True, unique=True, default=get_uuid)
    email = db.Column(db.String(150), unique=True)
    password = db.Column(db.Text, nullable=False)
Postman
Postman is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs—faster.
https://www.postman.com/

run (venv) C:\flask_dev\flaskreact>flask run

React JS
https://create-react-app.dev/

Create Project
C:\react-js>npx create-react-app myreactdev

Run
C:\react-js\myreactdev> npm start
C:\react-js\myreactdev\src\App.js
//C:\react-js\myreactdev\src\App.js
import React, { } from 'react';
import './App.css';
 
import {BrowserRouter, Routes, Route, Link} from 'react-router-dom';
 
import LandingPage from "./pages/LandingPage";
import LoginPage from './pages/LoginPage'
import RegisterPage from './pages/RegisterPage'

function App() {
  return (
    <div className="vh-100 gradient-custom">
    <div className="container">
      <h1 className="page-header text-center">React and Python Flask Login Register</h1>
  
      <BrowserRouter>
        <Routes>
            <Route path="/" element={<LandingPage />} />
            <Route path="/login" element={<LoginPage />} />
            <Route path="/register" element={<RegisterPage />} />
        </Routes>
      </BrowserRouter>
    </div>
    </div>
  );
}
  
export default App;
Install React Router Dom
https://www.npmjs.com/package/react-router-dom
C:\react-js\myreactdev>npm i react-router-dom --save
Install Axios
https://www.npmjs.com/package/axios
C:\react-js\myreactdev>npm install axios --save

C:\react-js\myreactdev\src\pages\LandingPage.js
//C:\react-js\myreactdev\src\pages\LandingPage.js
import React, { } from "react";

import {Link} from 'react-router-dom';

export default function LandingPage(){

  return (
    <div>
        <div className="container h-100">
            <div className="row h-100">
				<div className="col-12">
					<h1>Welcome to this React Application</h1>
					<p><Link to="/login" className="btn btn-success">Login</Link> | <Link to="/register" className="btn btn-success">register</Link> </p>
				</div>
            </div>
        </div>
    </div>
  );
}
C:\react-js\myreactdev\src\pages\LoginPage.js
//C:\react-js\myreactdev\src\pages\LoginPage.js
import React, { useState } from "react";
import axios from 'axios';
import {useNavigate} from "react-router-dom";

export default function LoginPage(){

    const [email,setEmail] = useState('');
    const [password,setPassword] = useState('');
  
	const navigate = useNavigate();
	
	const logInUser = () => {
        if(email.length === 0){
          alert("Email has left Blank!");
        }
        else if(password.length === 0){
          alert("password has left Blank!");
        }
        else{
            axios.post('http://127.0.0.1:5000/login', {
                email: email,
                password: password
            })
            .then(function (response) {
                console.log(response);
                //console.log(response.data);
				navigate("/");
            })
            .catch(function (error) {
                console.log(error, 'error');
				if (error.response.status === 401) {
					alert("Invalid credentials");
				}
            });
        }
    }

	let imgs = [
	  'https://as1.ftcdn.net/v2/jpg/03/39/70/90/1000_F_339709048_ZITR4wrVsOXCKdjHncdtabSNWpIhiaR7.jpg',
	];
	
  return (
    <div>
        <div className="container h-100">
		  <div className="container-fluid h-custom">
			<div className="row d-flex justify-content-center align-items-center h-100">
			  <div className="col-md-9 col-lg-6 col-xl-5">
				<img src={imgs[0]} className="img-fluid"/>
			  </div>
			  <div className="col-md-8 col-lg-6 col-xl-4 offset-xl-1">
				<form>
				  <div className="d-flex flex-row align-items-center justify-content-center justify-content-lg-start">
					<p className="lead fw-normal mb-0 me-3">Log Into Your Account</p>
				  </div>

				  <div className="form-outline mb-4">
					<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} id="form3Example3" className="form-control form-control-lg" placeholder="Enter a valid email address" />
					<label className="form-label" for="form3Example3">Email address</label>
				  </div>

			
				  <div className="form-outline mb-3">
					<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} id="form3Example4" className="form-control form-control-lg" placeholder="Enter password" />
					<label className="form-label" for="form3Example4">Password</label>
				  </div>

				  <div className="d-flex justify-content-between align-items-center">
					<div className="form-check mb-0">
					  <input className="form-check-input me-2" type="checkbox" value="" id="form2Example3" />
					  <label className="form-check-label" for="form2Example3">
						Remember me
					  </label>
					</div>
					<a href="#!" className="text-body">Forgot password?</a>
				  </div>

				  <div className="text-center text-lg-start mt-4 pt-2">
					<button type="button" className="btn btn-primary btn-lg" onClick={logInUser} >Login</button>
					<p className="small fw-bold mt-2 pt-1 mb-0">Don't have an account? <a href="/register" className="link-danger">Register</a></p>
				  </div>

				</form>
			  </div>
			</div>
		  </div>
		</div>
    </div>
  );
}
C:\react-js\myreactdev\src\pages\RegisterPage.js
//C:\react-js\myreactdev\src\pages\RegisterPage.js
import React, { useState } from "react";
import axios from 'axios';
import {useNavigate} from "react-router-dom";

export default function RegisterPage(){

    const [email,setEmail] = useState('');
    const [password,setPassword] = useState('');
  
	const navigate = useNavigate();
	
	const registerUser = () => {
        axios.post('http://127.0.0.1:5000/signup', {
            email: email,
            password: password
        })
        .then(function (response) {
             console.log(response);
			navigate("/");
        })
        .catch(function (error) {
            console.log(error, 'error');
			if (error.response.status === 401) {
				alert("Invalid credentials");
			}
        });
	};
	
	let imgs = [
	  'https://as2.ftcdn.net/v2/jpg/03/39/70/91/1000_F_339709132_H9HSSTtTmayePcbARkTSB2qoZTubJ6bR.jpg',
	];
	
  return (
    <div>
        <div className="container h-100">
		  <div className="container-fluid h-custom">
			<div className="row d-flex justify-content-center align-items-center h-100">
			  <div className="col-md-8 col-lg-6 col-xl-4 offset-xl-1">
				<form>
				  <div className="d-flex flex-row align-items-center justify-content-center justify-content-lg-start">
					<p className="lead fw-normal mb-0 me-3">Create Your Account</p>
				  </div>

				  <div className="form-outline mb-4">
					<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} id="form3Example3" className="form-control form-control-lg" placeholder="Enter a valid email address" />
					<label className="form-label" for="form3Example3">Email address</label>
				  </div>

			
				  <div className="form-outline mb-3">
					<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} id="form3Example4" className="form-control form-control-lg" placeholder="Enter password" />
					<label className="form-label" for="form3Example4">Password</label>
				  </div>

				  <div className="d-flex justify-content-between align-items-center">
					<div className="form-check mb-0">
					  <input className="form-check-input me-2" type="checkbox" value="" id="form2Example3" />
					  <label className="form-check-label" for="form2Example3">
						Remember me
					  </label>
					</div>
					<a href="#!" className="text-body">Forgot password?</a>
				  </div>

				  <div className="text-center text-lg-start mt-4 pt-2">
					<button type="button" className="btn btn-primary btn-lg" onClick={() => registerUser()} >Sign Up</button>
					<p className="small fw-bold mt-2 pt-1 mb-0">Login to your account <a href="/login" className="link-danger">Login</a></p>
				  </div>

				</form>
			  </div>
			  <div className="col-md-9 col-lg-6 col-xl-5">
				<img src={imgs[0]} className="img-fluid"/>
			  </div>
			</div>
		  </div>
		</div>
    </div>
  );
}
react-js\myreactdev\src\App.css
body {
  margin: 0;
  background-color: #ffffff;
}

.h-100 {
	margin-top:100px;
}	
Run C:\react-j\myreactdev>npm start
http://localhost:3000/

Python Flask Authentication Server-Sided Sessions

Python Flask Authentication Server-Sided Sessions

https://flask.palletsprojects.com/en/2.2.x/installation/
 
Create an environment
C:\flask_dev>py -3 -m venv venv

Activate the environment
C:\flask_dev>venv\Scripts\activate

Install Flask
venv C:\flask_dev>pip install Flask

Flask-Bcrypt
Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.
https://pypi.org/project/Flask-Bcrypt/

(venv) PS C:\flask_dev\flaskreact>pip install Flask-Bcrypt

Flask-Session
Flask-Session is an extension for Flask that adds support for Server-side Session to your application.
https://flask-session.readthedocs.io/en/latest/

(venv) PS C:\flask_dev\flaskreact>pip install Flask-Session

python-dotenv
Python-dotenv reads key-value pairs from a .env file and can set them as environment variables.
https://pypi.org/project/python-dotenv/

(venv) PS C:\flask_dev\flaskreact>pip install python-dotenv

Flask-SQLAlchemy
Flask-SQLAlchemy is an extension for Flask that adds support for SQLAlchemy to your application.
https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/

(venv) PS C:\flask_dev\flaskreact>pip install -U Flask-SQLAlchemy
C:\flask_dev\flaskreact\app.py

 
#C:\flask_dev\flaskreact\app.py
from flask import Flask, request, jsonify, session
from flask_bcrypt import Bcrypt #pip install Flask-Bcrypt = https://pypi.org/project/Flask-Bcrypt/
from flask_session import Session #pip install Flask-Session = https://flask-session.readthedocs.io/en/latest/

from dotenv import load_dotenv #pip install python-dotenv = https://pypi.org/project/python-dotenv/
load_dotenv()

from models import db, User
from datetime import timedelta

app = Flask(__name__)

app.config['SESSION_PERMANENT'] = True
app.config['SESSION_TYPE'] = 'filesystem'
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=5)

# The maximum number of items the session stores before it starts deleting some, default 500
app.config['SESSION_FILE_THRESHOLD'] = 100  


app.config['SECRET_KEY'] = 'cairocoders-ednalan'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskdb.db'

SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True

bcrypt = Bcrypt(app)
server_session = Session(app)
db.init_app(app)

with app.app_context():
    db.create_all()

@app.route("/profile")
def profile():
    user_id = session.get("user_id")

    if not user_id:
        return jsonify({"error": "Unauthorized Access"}), 401
    
    user = User.query.filter_by(id=user_id).first()
    return jsonify({
        "id": user.id,
        "email": user.email
    }) 

@app.route("/signup", methods=["POST"])
def signup():
    email = request.json["email"]
    password = request.json["password"]

    user_exists = User.query.filter_by(email=email).first() is not None

    if user_exists:
        return jsonify({"error": "Email already exists"}), 409

    hashed_password = bcrypt.generate_password_hash(password)
    new_user = User(email=email, password=hashed_password)
    db.session.add(new_user)
    db.session.commit()
    
    session["user_id"] = new_user.id

    return jsonify({
        "id": new_user.id,
        "email": new_user.email
    })

@app.route("/login", methods=["POST"])
def login_user():
    email = request.json["email"]
    password = request.json["password"]

    user = User.query.filter_by(email=email).first()

    if user is None:
        return jsonify({"error": "Unauthorized Access"}), 401

    if not bcrypt.check_password_hash(user.password, password):
        return jsonify({"error": "Unauthorized"}), 401
    
    session["user_id"] = user.id

    return jsonify({
        "id": user.id,
        "email": user.email
    })

@app.route("/logout", methods=["POST"])
def logout_user():
    session.pop("user_id")
    return "200"

if __name__ == "__main__":
    app.run(debug=True)
C:\flask_dev\flaskreact\models.py
 
#C:\flask_dev\flaskreact\models.py
from flask_sqlalchemy import SQLAlchemy
from uuid import uuid4

db = SQLAlchemy()

def get_uuid():
    return uuid4().hex

class User(db.Model):
    __tablename__ = "users"
    id = db.Column(db.String(11), primary_key=True, unique=True, default=get_uuid)
    email = db.Column(db.String(150), unique=True)
    password = db.Column(db.Text, nullable=False)
Postman
Postman is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs—faster.
https://www.postman.com/

run (venv) C:\flask_dev\flaskreact>flask run

Thursday, April 13, 2023

Python Flask and React

Python Flask and React

https://flask.palletsprojects.com/en/2.2.x/installation/
 
Create an environment
C:\flask_dev>py -3 -m venv venv

Activate the environment
C:\flask_dev>venv\Scripts\activate

Install Flask
venv C:\flask_dev>pip install Flask
C:\flask_dev\flaskreact\app.py
 
#C:\flask_dev\flaskreact\app.py
from flask import Flask
from flask_restful import Api, Resource, reqparse #ModuleNotFoundError: No module named 'flask_restful' = pip install flask-restful
from flask_cors import CORS #ModuleNotFoundError: No module named 'flask_cors' = pip install Flask-Cors
from api.ApiHandler import ApiHandler

app = Flask(__name__)

CORS(app)
api = Api(app)

api.add_resource(ApiHandler, '/flask')

@app.route("/")
def hello_world():
    return "

Hello, World!

" if __name__ == '__main__': app.run(debug=True)
C:\flask_dev\flaskreact\api\ApiHandler.py
 
#C:\flask_dev\flaskreact\api\ApiHandler.py
from flask_restful import Api, Resource

class ApiHandler(Resource):
  def get(self):
    return {
      'resultStatus': 'SUCCESS',
      'message': "Hello Api Handler ApiHandler.py"
      }
flask run (venv) C:\flask_dev\flaskreact>flask run:
React JS

Create Project
C:\react-js>npx create-react-app myreactdev

Run
C:\react-js\myreactdev> npm start

C:\react-js\myreactdev\src\App.js
//C:\react-js\myreactdev\src\App.js
import './App.css';
import React, { useEffect, useState } from 'react';
import axios from 'axios'

function App() {
  const [getMessage, setGetMessage] = useState({})

  useEffect(()=>{
    axios.get('http://localhost:5000/flask').then(response => {
      console.log("SUCCESS", response)
      setGetMessage(response)
    }).catch(error => {
      console.log(error)
    })

  }, [])
  return (
    <div className="App">
      <header className="App-header">
        <p><h1>Python Flask and React</h1></p>
        <div>{getMessage.status === 200 ? 
          <h3>{getMessage.data.message}</h3>
          :
          <h3>LOADING</h3>}</div>
      </header>
    </div>
  );
}

export default App;
Run C:\react-j\myreactdev>npm start

Wednesday, March 29, 2023

Convert Python Flask App to exe File || Convert py to exe file

Convert Python Flask App to exe File || Convert py to exe file

https://flask.palletsprojects.com/en/2.2.x/installation/
 
Create an environment
C:\flask_dev>py -3 -m venv venv

Activate the environment
C:\flask_dev>venv\Scripts\activate

Install Flask
venv C:\flask_dev>pip install Flask

C:\flask_dev\flasktoexe\app.py
#C:\flask_dev\flasktoexe\app.py
from flask import Flask,render_template

import webview

app = Flask(__name__, static_folder='./static', template_folder='./templates')

@app.route('/')
def home():
    return render_template("index.html",name='cairocoders Home page')

@app.route('/page2')
def page2():
    return render_template("page2.html",name='cairocoders page 2')
    
webview.create_window('Flask to exe', app)

if __name__ == '__main__':
    #app.run(debug=True)
    webview.start()
install pywebview
pywebview is a lightweight cross-platform wrapper around a webview component that allows to display HTML content in its own native GUI window.
https://pypi.org/project/pywebview/
C:\flask_dev>pip install pywebview

templates/index.html
//templates/index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Calculator</title>
    <link href="{{ url_for('static',filename='style.css') }}" rel="stylesheet">
    <script src="{{ url_for('static',filename='script.js') }}" defer></script>
  </head>
  <body>
    <div class="calculator-grid">
    <div class="output">
    <div data-previous-operand class="previous-operand"></div>
    <div data-current-operand class="current-operand"></div>
    </div>
    <button data-all-clear class="span-two">AC</button>
    <button data-delete class="operation">DEL</button>
    <button data-operation class="operation">÷</button>
    <button data-number>1</button>
    <button data-number>2</button>
    <button data-number>3</button>
    <button data-operation class="operation">*</button>
    <button data-number>4</button>
    <button data-number>5</button>
    <button data-number>6</button>
    <button data-operation class="operation">+</button>
    <button data-number>7</button>
    <button data-number>8</button>
    <button data-number>9</button>
    <button data-operation class="operation">-</button>
    <button data-number>.</button>
    <button data-number>0</button>
    <button data-equals class="span-two">=</button>

    </div>
    <a href="/page2">Page 2</a>
  </body>
</html>
templates/page2.html
//templates/page2.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Page 2</title>
  </head>
  <body>
<h1>Page2</h1>
<a href="/">Home</a>
  </body>
</html>
static/style.html
//static/style.html
*, *::before, *::after {
  box-sizing: border-box;
  font-family: Gotham Rounded, sans-serif;
  font-weight: normal;
}

body {
  margin: 0;
  padding: 0;
  background: linear-gradient(to right, #0187d0, #a5c2c8);
  }

  .calculator-grid {
    display: grid;
    justify-content: center;
    align-content: center;
    min-height: 100vh;
    grid-template-columns: repeat(4, 100px);
    grid-template-rows: minmax(120px, auto) repeat(5, 100px);
    }

    .calculator-grid > button {
      cursor: pointer;
      font-size: 2rem;
      border: 1px, solid #FFFFFF;
      outline: none;     
    }

      .calculator-grid > button:hover {
        background-color: #a5a5a5;
      }

      .span-two {
        grid-column: span 2;
        color: #adf802;
        background-color: #fd9502;
      }
      .operation {
        color: #ffffff;
        background-color: #fd9502;
      }
      .output{
        grid-column: 1 / -1;
        background-color: rgba(0, 0, 0, 0.75);
        display: flex;
        align-items: flex-end;
        justify-content: space-around;
        flex-direction: column;
        padding: 10px;
        word-wrap: break-word;
        word-break: break-all;
      }

      .output .previous-operand{
        color: rgba(255,255, 255, 0.75);
        font-size: 1.5rem;
      }

      .output .current-operand{
        color: white;
        font-size: 2.5rem;
      }
static/script.js
//static/script.js
class Calculator {
    constructor(previousOperandTextElement, currentOperandTextElement) {
      this.previousOperandTextElement = previousOperandTextElement
      this.currentOperandTextElement = currentOperandTextElement
      this.clear()
    }
  
    clear() {
      this.currentOperand = ''
      this.previousOperand = ''
      this.operation = undefined
    }
  
    delete() {
      this.currentOperand = this.currentOperand.toString().slice(0, -1)
    }
  
    appendNumber(number) {
      if (number === '.' && this.currentOperand.includes('.')) return
      this.currentOperand = this.currentOperand.toString() + number.toString()
    }
  
    chooseOperation(operation) {
      if (this.currentOperand === '') return
      if (this.previousOperand !== '') {
        this.compute()
      }
      this.operation = operation
      this.previousOperand = this.currentOperand
      this.currentOperand = ''
    }
  
    compute() {
      let computation
      const prev = parseFloat(this.previousOperand)
      const current = parseFloat(this.currentOperand)
      if (isNaN(prev) || isNaN(current)) return
      switch (this.operation) {
        case '+':
          computation = prev + current
          break
        case '-':
          computation = prev - current
          break
        case '*':
          computation = prev * current
          break
        case '÷':
          computation = prev / current
          break
        default:
          return
      }
      this.currentOperand = computation
      this.operation = undefined
      this.previousOperand = ''
    }
  
    getDisplayNumber(number) {
      const stringNumber = number.toString()
      const integerDigits = parseFloat(stringNumber.split('.')[0])
      const decimalDigits = stringNumber.split('.')[1]
      let integerDisplay
      if (isNaN(integerDigits)) {
        integerDisplay = ''
      } else {
        integerDisplay = integerDigits.toLocaleString('en', { maximumFractionDigits: 0 })
      }
      if (decimalDigits != null) {
        return `${integerDisplay}.${decimalDigits}`
      } else {
        return integerDisplay
      }
    }
  
    updateDisplay() {
      this.currentOperandTextElement.innerText =
        this.getDisplayNumber(this.currentOperand)
      if (this.operation != null) {
        this.previousOperandTextElement.innerText =
          `${this.getDisplayNumber(this.previousOperand)} ${this.operation}`
      } else {
        this.previousOperandTextElement.innerText = ''
      }
    }
  }
  
  
  const numberButtons = document.querySelectorAll('[data-number]')
  const operationButtons = document.querySelectorAll('[data-operation]')
  const equalsButton = document.querySelector('[data-equals]')
  const deleteButton = document.querySelector('[data-delete]')
  const allClearButton = document.querySelector('[data-all-clear]')
  const previousOperandTextElement = document.querySelector('[data-previous-operand]')
  const currentOperandTextElement = document.querySelector('[data-current-operand]')
  
  const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement)
  
  numberButtons.forEach(button => {
    button.addEventListener('click', () => {
      calculator.appendNumber(button.innerText)
      calculator.updateDisplay()
    })
  })
  
  operationButtons.forEach(button => {
    button.addEventListener('click', () => {
      calculator.chooseOperation(button.innerText)
      calculator.updateDisplay()
    })
  })
  
  equalsButton.addEventListener('click', button => {
    calculator.compute()
    calculator.updateDisplay()
  })
  
  allClearButton.addEventListener('click', button => {
    calculator.clear()
    calculator.updateDisplay()
  })
  
  deleteButton.addEventListener('click', button => {
    calculator.delete()
    calculator.updateDisplay()
  })
  
  document.addEventListener('keydown', function (event) {
    let patternForNumbers = /[0-9]/g;
    let patternForOperators = /[+\-*\/]/g
    if (event.key.match(patternForNumbers)) {
      event.preventDefault();
      calculator.appendNumber(event.key)
      calculator.updateDisplay()
    }
    if (event.key === '.') {
      event.preventDefault();
      calculator.appendNumber(event.key)
      calculator.updateDisplay()
    }
    if (event.key.match(patternForOperators)) {
      event.preventDefault();
      calculator.chooseOperation(event.key)
      calculator.updateDisplay()
    }
    if (event.key === 'Enter' || event.key === '=') {
      event.preventDefault();
      calculator.compute()
      calculator.updateDisplay()
    }
    if (event.key === "Backspace") {
      event.preventDefault();
      calculator.delete()
      calculator.updateDisplay()
    }
    if (event.key == 'Delete') {
      event.preventDefault();
      calculator.clear()
      calculator.updateDisplay()
    }
  
  });
run (venv) C:\flask_dev\flasktoexe>flask run

convert to exe file

install Auto PY to EXE
Converts .py to .exe using a simple graphical interface.

https://pypi.org/project/auto-py-to-exe/
C:\>pip install auto-py-to-exe

execute terminal:
C:\>auto-py-to-exe

Monday, February 13, 2023

Python Flask Simple To Do - SQLAlchemy

Python Flask Simple To Do - SQLAlchemy

pip install Flask
pip install Flask-SQLAlchemy

todo/app.py
//todo/app.py
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)


class Todo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100))
    complete = db.Column(db.Boolean)


db.create_all()

@app.route('/')
def home():
    todo_list = db.session.query(Todo).all()
    # return "Hello, World!"
    return render_template("index.html", todo_list=todo_list)


@app.route("/add", methods=["POST"])
def add():
    title = request.form.get("title")
    new_todo = Todo(title=title, complete=False)
    db.session.add(new_todo)
    db.session.commit()
    return redirect(url_for("home"))

@app.route("/update/<int:todo_id>")
def update(todo_id):
    todo = db.session.query(Todo).filter(Todo.id == todo_id).first()
    todo.complete = not todo.complete
    db.session.commit()
    return redirect(url_for("home"))

@app.route("/delete/<int:todo_id>")
def delete(todo_id):
    todo = db.session.query(Todo).filter(Todo.id == todo_id).first()
    db.session.delete(todo)
    db.session.commit()
    return redirect(url_for("home"))

if __name__ == '__main__':
	app.run(debug=True)
Bootstrap 5
https://getbootstrap.com/docs/5.0/getting-started/introduction/

templates/index.html
//templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python Flask Simple To Do - SQLAlchemy</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css">
</head>
<body>
<section class="vh-100" style="background-color: #eee;">
  <div class="container py-5 h-100">
    <div class="row d-flex justify-content-center align-items-center h-100">
      <div class="col col-lg-9 col-xl-7">
        <div class="card rounded-3">
          <div class="card-body p-4">
 
            <h4 class="text-center my-3 pb-3">Python Flask Simple To Do - SQLAlchemy</h4>
            <form class="row" action="/add" method="post">
              <div class="col-4">
                <div class="form-outline">
                  <input type="text" id="title" name="title" class="form-control" placeholder="Enter a task here"/>
                </div>
              </div>
 
              <div class="col-6">
                <button type="submit" class="btn btn-primary">Save</button>
              </div>
            </form>
 
            <table class="table mb-4">
                <thead>
                    <tr>
                      <th scope="col">No.</th>
                      <th scope="col">Todo item</th>
                      <th scope="col">Status</th>
                      <th scope="col">Actions</th>
                    </tr>
                </thead>
                <tbody>
                    {% for todo in todo_list %}
                    <tr>
                      <th scope="row">{{todo.id }}</th>
                      <td>{{ todo.title }}</td>
                      <td>
                        {% if todo.complete == False %}
                        <div class="alert alert-secondary" role="alert">In progress</div>
                        {% else %}
                        <div class="alert alert-success" role="alert">Completed</div>
                        {% endif %}
                      </td>
                      <td>
                        <a class="btn btn-success" href="/update/{{ todo.id }}">Update</a>
                        <a class="btn btn-danger ms-1" href="/delete/{{ todo.id }}">Delete</a>
                      </td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>
</body>
</html>  
run (venv) C:\flask_dev\todo>flask run

Tuesday, January 25, 2022

Python Flask Vuejs CRUD (Create, Read, Update and Delete) with Mysql

Python Flask Vuejs CRUD (Create, Read, Update and Delete) with Mysql


https://bootstrap-vue.org/

https://bootstrap-vue.org/docs/components/modal#modals

https://vuejs.org/v2/guide/

Install Flask-CORS extension https://flask-cors.readthedocs.io/

$ pip install -U flask-cors
from flask_cors import CORS

https://github.com/axios/axios

CREATE TABLE `members` (
  `id` int(11) NOT NULL,
  `firstname` varchar(30) NOT NULL,
  `lastname` varchar(30) NOT NULL,
  `address` varchar(150) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `members` (`id`, `firstname`, `lastname`, `address`) VALUES
(1, 'Airi', 'Satou', 'Tokyo'),
(2, 'Angelica ', 'Ramos', 'London'),
(3, 'Ashton ', 'Cox', 'San Francisco'),
(4, 'Bradley', 'Greer', 'London'),
(5, 'Brenden ', 'Wagner', 'San Francisco'),
(40, 'Brielle', 'Williamson', 'New York'),
(54, 'Bruno', 'Nash', 'London'),
(55, 'Caesar', 'Vance', 'New York'),
(56, 'Cara', 'Stevens', 'New York'),
(57, 'Cedric', 'Kelly', 'Edinburgh'),
(58, 'Zorita Serran', 'Satou', 'Tokyo'),
(59, 'Angelica ', 'Ramos', 'London'),
(60, 'Ashton ', 'Cox', 'San Francisco'),
(61, 'Bradley ', 'Greer', 'London'),
(62, 'Brenden ', 'Wagner', 'San Francisco'),
(63, 'Brielle', 'Williamson', 'New York'),
(64, 'Bruno', 'Nash', 'London'),
(65, 'Caesar', 'Vance', 'New York'),
(66, 'Cara', 'Stevens', 'New York'),
(67, 'Brenden ', 'Wagner', 'San Francisco'),
(68, 'Brielle', 'Williamson', 'New York'),
(69, 'Bruno', 'Nash', 'London'),
(70, 'Caesar', 'Vance', 'New York'),
(71, 'Cara', 'Stevens', 'New York'),
(72, 'Cedric', 'Kelly', 'Edinburgh');

ALTER TABLE `members`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `members`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=73;
crud.html
//crud.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
<title>Python Flask Vuejs CRUD (Create, Read, Update and Delete) with PHP Mysql</title>
</head>
<body>
<div class="container" id="vuejscrudapp">
	<div class="row">
        <div class="col-md-12 mt-5">
          <h1 class="text-center">Python Flask Vuejs CRUD (Create, Read, Update and Delete) with PHP Mysql</h1>
          <hr>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
          <!-- Add Records -->
        <div>
            <b-button id="show-btn" @click="showModal('my-modal')">Add Records</b-button>
 
            <b-modal ref="my-modal" hide-footer title="Add Records">
              <div>
                <form action="" @submit.prevent="onSubmit">
                  <div class="form-group">
                    <label for="">First Name</label>
                    <input type="text" v-model="firstname" class="form-control">
                  </div>
                  <div class="form-group">
                    <label for="">Last Name</label>
                    <input type="text" v-model="lastname" class="form-control">
                  </div>
				  <div class="form-group">
                    <label for="">Address</label>
                    <input type="text" v-model="address" class="form-control">
                  </div>
                  <div class="form-group">
                    <button class="btn btn-sm btn-outline-info">Add Records</button>
                  </div>
                </form>
              </div>
              <b-button class="mt-3" variant="outline-danger" block @click="hideModal('my-modal')">Close Me</b-button>
            </b-modal>
        </div>
 
        <!-- Update Record -->
        <div>
            <b-modal ref="my-modal1" hide-footer title="Update Record">
              <div>
                <form action="" @submit.prevent="onUpdate">
                  <div class="form-group">
                    <label for="">First Name</label>
                    <input type="text" v-model="edit_id">
                    <input type="text" v-model="edit_firstname" class="form-control">
                  </div>
                  <div class="form-group">
                    <label for="">Last Name</label>
                    <input type="text" v-model="edit_lastname" class="form-control">
                  </div>
				  <div class="form-group">
                    <label for="">Address</label>
                    <input type="text" v-model="edit_address" class="form-control">
                  </div>
                  <div class="form-group">
                    <button class="btn btn-sm btn-outline-info">Update Record</button>
                  </div>
                </form>
              </div>
              <b-button class="mt-3" variant="outline-danger" block @click="hideModal('my-modal1')">Close Me</b-button>
            </b-modal>
          </div>
		  
        </div>
	</div>
	  
    <div class="row">
        <div class="col-md-12">
          <table class="table table-striped table-bordered">
            <thead>
              <tr>
                <th>ID</th>
                <th>First Name</th>
                <th>Last Name</th>
                <th>Address</th>
                <th>Action</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(record, i) in records" :key="record.id">
                <td>{{i + 1}}</td>
                <td>{{record.firstname}}</td>
                <td>{{record.lastname}}</td>
                <td>{{record.address}}</td>
                <td>
                  <button @click="deleteRecord(record.id)" class="btn btn-sm btn-outline-danger">Delete</button>
                  <button @click="editRecord(record.id)" class="btn btn-sm btn-outline-info">Edit</button>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
    </div>
</div>
 
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<!-- BootstrapVue js -->
<script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
<!-- Axios -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
    var app = new Vue({
        el: '#vuejscrudapp',
        data: {
			firstname: '',
			lastname: '',
			address: '',
			records: [],
			edit_id: '',
			edit_firstname: '',
			edit_lastname: '',
			edit_address: ''
        },
 
        methods: {
			showModal(id) {
				this.$refs[id].show()
			},
			hideModal(id) {
				this.$refs[id].hide()
			},
 
			onSubmit(){
				if (this.firstname !== '' && this.lastname !== '' && this.address !== '') {
					var config = { headers: {  
						'Content-Type': 'application/json',
						'Access-Control-Allow-Origin': '*'}
					}
					axios.post("http://127.0.0.1:5000/insert", 
						{ firstname : this.firstname, lastname : this.lastname, address : this.address}, config
					)
					.then(res => {
						console.log(res)
						alert('New record Successfully added')
						this.firstname = ''
						this.lastname = ''
						this.address = ''
		 
						app.hideModal('my-modal')
						app.getRecords()
					})
					.catch(err => {
						console.log(err)
					})
				}else{
				  alert('empty')
				}
			},
 
			getRecords(){
				axios({
				  url: 'http://localhost:5000/',
				  method: 'get'
				})
				.then(res => {
				  console.log(res)
				  this.records = res.data.members
				})
				.catch(err => {
				  console.log(err)
				})
			},
 
			editRecord(id){
				axios.get("http://127.0.0.1:5000/edit/" + id)
				.then(res => {
					console.log(res.data)
				    this.edit_id = res.data.editmember['id']
				    this.edit_firstname = res.data.editmember['firstname']
				    this.edit_lastname = res.data.editmember['lastname']
				    this.edit_address = res.data.editmember['address']
					app.showModal('my-modal1')
				})
				.catch(err => {
				  console.log(err)
				})
			},
			
			onUpdate(){
				if (this.edit_firstname !== '' && this.edit_lastname !== '' && this.edit_address !== '' && this.edit_id !== '') {

				    var config = { headers: {  
						'Content-Type': 'application/json',
						'Access-Control-Allow-Origin': '*'}
					}
					axios.post("http://127.0.0.1:5000/update", 
						{ edit_id : this.edit_id, edit_firstname : this.edit_firstname, edit_lastname : this.edit_lastname, edit_address : this.edit_address}, config
					)
					.then(res => {
						console.log(res)
						alert('record update');
		 
						this.edit_firstname = '';
						this.edit_lastname = '';
						this.edit_address = '';
						this.edit_id = '';
		 
						app.hideModal('my-modal1');
						app.getRecords();
					})
					  .catch(err => {
						console.log(err)
					})
	 
				}else{
				  alert('empty')
				}
			},
			
			deleteRecord(id){
				if (window.confirm('Delete this record')) {
					axios.get("http://127.0.0.1:5000/delete/" + id)
					.then(res => {
						console.log(res)
						alert('delete successfully')
						app.getRecords();
					})
					.catch(err => {
						console.log(err)
					})
				}
			},
		
        },
		  
        mounted: function(){
          this.getRecords()
        }
    })
</script>
</body>   
</html>
app.py
//app.py
from flask import Flask, jsonify, request
from flask_cors import CORS
from flaskext.mysql import MySQL #pip install flask-mysql
import pymysql

MEMBERS = [
    {
        'id': '1',
        'firstname': 'cairocoders',
        'lastname': 'Ednalan',
        'address': 'Olongapo city'
    },
    {
        'id': '2',
        'firstname': 'clydey',
        'lastname': 'Ednalan',
        'address': 'Angles city'
    }
]
# configuration
DEBUG = True

# instantiate the app
app = Flask(__name__)
app.config.from_object(__name__)
    
mysql = MySQL()
   
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = ''
app.config['MYSQL_DATABASE_DB'] = 'testingdb'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)

# enable CORS
CORS(app, resources={r'/*': {'origins': '*'}})


# sanity check route
@app.route('/ping', methods=['GET'])
def ping_pong():
    return jsonify('pong!')

@app.route('/members', methods=['GET'])
def all_members():
    return jsonify({
        'status': 'success',
        'members': MEMBERS
    })

@app.route('/')
def home():
    conn = mysql.connect()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    try:
        cursor.execute("SELECT * from members order by id")
        userslist = cursor.fetchall()
        return jsonify({
            'status': 'success',
            'members': userslist
        })
    except Exception as e:
        print(e)
    finally:
        cursor.close() 
        conn.close()

@app.route('/insert', methods=['GET', 'POST'])
def insert():
    conn = mysql.connect()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    response_object = {'status': 'success'}
    if request.method == 'POST':
        post_data = request.get_json(silent=True)
        firstname = post_data.get('firstname')
        lastname = post_data.get('lastname')
        address = post_data.get('address')

        print(firstname)
        print(lastname)

        sql = "INSERT INTO members(firstname,lastname,address) VALUES(%s, %s, %s)"
        data = (firstname, lastname, address)
        conn = mysql.connect()
        cursor = conn.cursor()
        cursor.execute(sql, data)
        conn.commit()

        response_object['message'] = "Successfully Added"
    return jsonify(response_object)

@app.route('/edit/<string:id>', methods=['GET', 'POST'])
def edit(id):
    conn = mysql.connect()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    print(id)
    cursor.execute("SELECT * FROM members WHERE id = %s", [id])
    row = cursor.fetchone() 

    return jsonify({
        'status': 'success',
        'editmember': row
    })

@app.route('/update', methods=['GET', 'POST'])
def update():
    conn = mysql.connect()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    response_object = {'status': 'success'}
    if request.method == 'POST':
        post_data = request.get_json(silent=True)
        edit_id = post_data.get('edit_id')
        edit_firstname = post_data.get('edit_firstname')
        edit_lastname = post_data.get('edit_lastname')
        edit_address = post_data.get('edit_address')

        print(edit_firstname)
        print(edit_lastname)

        cursor.execute ("UPDATE members SET firstname=%s, lastname=%s, address=%s WHERE id=%s",(edit_firstname, edit_lastname, edit_address, edit_id))
        conn.commit()
        cursor.close()

        response_object['message'] = "Successfully Updated"
    return jsonify(response_object)

@app.route('/delete/<string:id>', methods=['GET', 'POST'])
def delete(id):
    conn = mysql.connect()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
  
    response_object = {'status': 'success'}

    cursor.execute("DELETE FROM members WHERE id = %s", [id])
    conn.commit()
    cursor.close()
    response_object['message'] = "Successfully Deleted"
    return jsonify(response_object)

if __name__ == '__main__':
    app.run()

Sunday, January 23, 2022

Python Flask Vue.js fetchAll Data from Mysql Database

Python Flask Vue.js fetchAll Data from Mysql Database

Bootstrap 5.1 Version
https://getbootstrap.com/docs/5.1/getting-started/introduction/

Install Flask-CORS extension https://flask-cors.readthedocs.io/

$ pip install -U flask-cors
from flask_cors import CORS

https://github.com/axios/axios


CREATE TABLE `members` (
  `id` int(11) NOT NULL,
  `firstname` varchar(30) NOT NULL,
  `lastname` varchar(30) NOT NULL,
  `address` varchar(150) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `members` (`id`, `firstname`, `lastname`, `address`) VALUES
(1, 'Airi', 'Satou', 'Tokyo'),
(2, 'Angelica ', 'Ramos', 'London'),
(3, 'Ashton ', 'Cox', 'San Francisco'),
(4, 'Bradley', 'Greer', 'London'),
(5, 'Brenden ', 'Wagner', 'San Francisco'),
(40, 'Brielle', 'Williamson', 'New York'),
(54, 'Bruno', 'Nash', 'London'),
(55, 'Caesar', 'Vance', 'New York'),
(56, 'Cara', 'Stevens', 'New York'),
(57, 'Cedric', 'Kelly', 'Edinburgh'),
(58, 'Zorita Serran', 'Satou', 'Tokyo'),
(59, 'Angelica ', 'Ramos', 'London'),
(60, 'Ashton ', 'Cox', 'San Francisco'),
(61, 'Bradley ', 'Greer', 'London'),
(62, 'Brenden ', 'Wagner', 'San Francisco'),
(63, 'Brielle', 'Williamson', 'New York'),
(64, 'Bruno', 'Nash', 'London'),
(65, 'Caesar', 'Vance', 'New York'),
(66, 'Cara', 'Stevens', 'New York'),
(67, 'Brenden ', 'Wagner', 'San Francisco'),
(68, 'Brielle', 'Williamson', 'New York'),
(69, 'Bruno', 'Nash', 'London'),
(70, 'Caesar', 'Vance', 'New York'),
(71, 'Cara', 'Stevens', 'New York'),
(72, 'Cedric', 'Kelly', 'Edinburgh');

ALTER TABLE `members`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `members`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=73;


index.html
//index.html
<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Python Flask Vue.js fetchAll Data from Mysql Database</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
  <div class="container" id="fetchAlldiv">
   <br />
   <h3 align="center">Python Flask Vue.js fetchAll Data from Mysql Database</h3>
   <br />

   <div class="panel panel-default">
    <div class="panel-heading">
     <div class="row">
       <h3 class="panel-title"> Member List</h3>
     </div>
    </div>
    <div class="panel-body">
        <div class="table-responsive">
          <table class="table table-bordered table-striped">
           <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Address</th>
            <th>Edit</th>
            <th>Delete</th>
           </tr>
           <tr v-for="rs in allData">
			  <td>{{ rs.firstname }}</td>
              <td>{{ rs.lastname }}</td>
              <td>{{ rs.address }}</td>
            <td><button type="button" name="edit" class="btn btn-primary btn-xs edit">Edit</button></td>
            <td><button type="button" name="delete" class="btn btn-danger btn-xs delete">Delete</button></td>
           </tr>
          </table>
        </div>
    </div>
   </div>
</div>
<script>
var application = new Vue({
    el:'#fetchAlldiv',
    data:{
        allData:'',
    },
    methods:{
        fetchAllData:function(){ //show records
           axios.get('http://localhost:5000/')
		   .then(function(response){
				console.log(response);
				application.allData = response.data.members;
           });
        }
    }, 
    created:function(){
      this.fetchAllData();
    }
});
</script>
</body>
</html>
app.py
//app.py
from flask import Flask, jsonify
from flask_cors import CORS
from flaskext.mysql import MySQL #pip install flask-mysql
import pymysql

# configuration
DEBUG = True

# instantiate the app
app = Flask(__name__)
app.config.from_object(__name__)
    
mysql = MySQL()
   
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = ''
app.config['MYSQL_DATABASE_DB'] = 'testingdb'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)

# enable CORS
CORS(app, resources={r'/*': {'origins': '*'}})

@app.route('/')
def home():
    conn = mysql.connect()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    try:
        cursor.execute("SELECT * from members order by id")
        userslist = cursor.fetchall()
        return jsonify({
            'status': 'success',
            'members': userslist
        })
    except Exception as e:
        print(e)
    finally:
        cursor.close() 
        conn.close()

if __name__ == '__main__':
    app.run()

Tuesday, January 11, 2022

Python Flask Vue.js Axios - List All Data

Python Flask Vue.js Axios - List All Data

Install Flask-CORS extension https://flask-cors.readthedocs.io/

$ pip install -U flask-cors
from flask_cors import CORS

We'll be using the Vue CLI  https://cli.vuejs.org/

$ vue create client
This will require you to answer a few questions about the project.

Vue CLI v4.5.11
? Please pick a preset: (Use arrow keys)
❯ Default ([Vue 2] babel, eslint)
  Default (Vue 3 Preview) ([Vue 3] babel, eslint)
  Manually select features

Use the down arrow key to highlight

Run development server:
$ cd client
$ npm run serve

Install Bootstrap https://getbootstrap.com/docs/5.0/getting-started/download/
$ npm install bootstrap

Install Axios
https://github.com/axios/axios
$ npm install axios
app.py
 
from flask import Flask, jsonify
from flask_cors import CORS

MEMBERS = [
    {
        'id': '1',
        'name': 'cairocoders Ednalan',
        'email': 'cairocoders@gmail.com',
        'address': 'Olongapo city'
    },
    {
        'id': '2',
        'name': 'clydey Ednalan',
        'email': 'clydey@gmail.com',
        'address': 'Angles city'
    },
    {
        'id': '3',
        'name': 'claydren Ednalan',
        'email': 'clyderen@gmail.com',
        'address': 'San Fernando city'
    }
]

# configuration
DEBUG = True

# instantiate the app
app = Flask(__name__)
app.config.from_object(__name__)

# enable CORS
CORS(app, resources={r'/*': {'origins': '*'}})


# sanity check route
@app.route('/ping', methods=['GET'])
def ping_pong():
    return jsonify('pong!')

@app.route('/members', methods=['GET'])
def all_members():
    return jsonify({
        'status': 'success',
        'members': MEMBERS
    })

if __name__ == '__main__':
    app.run()
client/scr/main.js
//client/scr/main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router';
import 'bootstrap/dist/css/bootstrap.css';

Vue.config.productionTip = false

new Vue({
  router,
  render: (h) => h(App),
}).$mount('#app');
client/src/App.vue
//client/src/App.vue
<template>
  <div id="app">
    <router-view/>
  </div>
</template>
client/src/Ping.vue
//client/src/Ping.vue
<template>
  <div>
    <p>{{ msg }}</p>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  name: 'Ping',
  data() {
    return {
      msg: '',
    };
  },
  methods: {
    getMessage() {
      const path = 'http://localhost:5000/ping';
      axios.get(path)
        .then((res) => {
          console.log(res)
          this.msg = res.data;
        })
        .catch((error) => {
          console.error(error);
        });
    },
  },
  created() {
    this.getMessage();
  },
};
</script>
client/src/components/Home.vue
//client/src/components/Home.vue
<template>
  <div class="container">
    <div class="row">
      <div class="col-sm-10">
        <h1>Member</h1>
        <hr><br><br>
        <button type="button" class="btn btn-success btn-sm">Add Member</button>
        <br><br>
        <table class="table table-hover">
          <thead>
            <tr>
              <th scope="col">Name</th>
              <th scope="col">Email</th>
              <th scope="col">Address</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(rs, index) in members" :key="index">
              <td>{{ rs.name }}</td>
              <td>{{ rs.email }}</td>
              <td>{{ rs.address }}</td>
              <td>
                <div class="btn-group" role="group">
                  <button type="button" class="btn btn-warning btn-sm">Update</button>
                  <button type="button" class="btn btn-danger btn-sm">Delete</button>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      members: [],
    };
  },
  methods: {
    getMembers() {
      const path = 'http://localhost:5000/members';
      axios.get(path)
        .then((res) => {
          console.log(res);
          this.members = res.data.members;
        })
        .catch((error) => {
          console.error(error);
        });
    },
  },
  created() {
    this.getMembers();
  },
};
</script>
client/src/router/index.js
//client/src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import Ping from '../components/Ping.vue';
import Home from '../components/Home.vue';

Vue.use(Router);

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home,
    },
    {
      path: '/ping',
      name: 'Ping',
      component: Ping,
    },
  ],
});

Wednesday, November 17, 2021

Python Flask Upload multiple images and display with Progress Bar Jquery Ajax

Python Flask Upload multiple images and display with Progress Bar Jquery Ajax

jQuery Form Plugin allows you to easily and unobtrusively upgrade HTML forms to use AJAX.

https://github.com/jquery-form/form
bootstrap progressbar https://getbootstrap.com/docs/4.0/components/progress/

app.py
//app.py
from flask import Flask, flash, request, redirect, url_for, render_template, jsonify
import os
from werkzeug.utils import secure_filename
import urllib.request
 
app = Flask(__name__)
         
UPLOAD_FOLDER = 'static/uploads/'

app.secret_key = "cairocoders-ednalan"
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
 
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])

def allowed_file(filename):
	return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
 
@app.route('/')
def index(): 
    return render_template('index.html')
 
@app.route('/', methods=['POST'])
def upload():
	if 'uploadFile[]' not in request.files:
		return redirect(request.url)
	files = request.files.getlist('uploadFile[]')
	file_names = []
	for file in files:
		if file and allowed_file(file.filename):
			filename = secure_filename(file.filename)
			file_names.append(filename)
			file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
			msg  = 'File successfully uploaded to /static/uploads!'
		else:
			msg  = 'Invalid Uplaod only png, jpg, jpeg, gif'
	return jsonify({'htmlresponse': render_template('response.html', msg=msg, filenames=file_names)})

if __name__ == "__main__":
    app.run(debug=True)
templates/index.html
//templates/index.html
<!DOCTYPE html>
<html>
<head>
<title>Python Flask Upload multiple images and display with Progress Bar Jquery Ajax</title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.3.0/jquery.form.min.js" integrity="sha384-qlmct0AOBiA2VPZkMY3+2WqkHtIQ9lSdAsAn5RUJD/3vA5MKDgSGcdmIv4ycVxyn" crossorigin="anonymous"></script>
</head>
    <body>
        <div class="container">
            <br />
            <h3 align="center">Python Flask Upload multiple images and display with Progress Bar Jquery Ajax</h3>
            <br />
            <div class="panel panel-default">
                <div class="panel-heading"><b>Ajax File Upload Progress Bar using JQuery Ajax</b></div>
                <div class="panel-body">
					<form id="uploadImage" method="post" action="/" enctype="multipart/form-data">
                        <div class="form-group">
                            <label>File Upload</label>
                            <input type="file" name="uploadFile[]" multiple="true" id="uploadFile" accept=".jpg, .png" />
                        </div>
                        <div class="form-group">
                            <input type="submit" id="uploadSubmit" value="Upload" class="btn btn-info" />
                        </div>
                        <div class="progress">
                            <div class="progress-bar progress-bar-striped bg-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
                        </div>
                        <div id="targetLayer" style="display:none;"></div>
                    </form>
                </div>
            </div>
        </div>
<script>
$(document).ready(function(){
    $('#uploadImage').submit(function(event){
        if($('#uploadFile').val()){
            event.preventDefault();
            $('#loader-icon').show();
            $('#targetLayer').hide();
            $(this).ajaxSubmit({
                target: '#targetLayer',
                beforeSubmit:function(){
                    $('.progress-bar').width('50%');
                },
                uploadProgress: function(event, position, total, percentageComplete)
                {
                    $('.progress-bar').animate({
                        width: percentageComplete + '%'
                    }, {
                        duration: 1000
                    });
                },
                success:function(data){
                    $('#loader-icon').hide();
                    $('#targetLayer').show();
                    $('#targetLayer').append(data.htmlresponse);
                },
                resetForm: true
            });
        }
        return false;
    });
});
</script>
</body>
</html>
templates/response.html
//templates/response.html
<p><b>{{ msg }}</b></p>
{% if filenames %}
	{% for filename in filenames %}
  <div style="padding:20px;float:left;">
    <img width="500" src="/static/uploads/{{ filename }}"> 
  </div>
	{% endfor %}
{% endif %}

Sunday, November 14, 2021

Python Flask Upload multiple images and display multiple images uploaded

Python Flask Upload multiple images and display multiple images uploaded

app.py
//app.py
from flask import Flask, flash, request, redirect, url_for, render_template
import urllib.request
import os
from werkzeug.utils import secure_filename
import urllib.request

app = Flask(__name__)
 
UPLOAD_FOLDER = 'static/uploads/'

app = Flask(__name__)
app.secret_key = "cairocoders-ednalan"
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
 
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])

def allowed_file(filename):
	return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
	
@app.route('/')
def upload_form():
	return render_template('upload.html')

@app.route('/', methods=['POST'])
def upload_image():
	if 'files[]' not in request.files:
		flash('No file part')
		return redirect(request.url)
	files = request.files.getlist('files[]')
	file_names = []
	for file in files:
		if file and allowed_file(file.filename):
			filename = secure_filename(file.filename)
			file_names.append(filename)
			file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
		else:
			flash('Allowed image types are -> png, jpg, jpeg, gif')
			return redirect(request.url)

	return render_template('upload.html', filenames=file_names)

@app.route('/display/<filename>')
def display_image(filename):
	#print('display_image filename: ' + filename)
	return redirect(url_for('static', filename='uploads/' + filename), code=301)
 
if __name__ == "__main__":
    app.run()
templates/upload.html
//templates/upload.html
<html>
<head>
<title>Python Flask Upload multiple images and display multiple images uploaded</title>
</head>
<body>
<div style="padding:20px;">
<h2>Python Flask Upload multiple images and display multiple images uploaded</h2>
<p>
	{% with messages = get_flashed_messages() %}
	  {% if messages %}
		<ul class=flashes>
		{% for message in messages %}
		  <li>{{ message }}</li>
		{% endfor %}
		</ul>
	  {% endif %}
	{% endwith %}
</p>
<form method="post" action="/" enctype="multipart/form-data">
    <dl>
		<p>
			<input type="file" name="files[]" multiple="true" autocomplete="off" required>
		</p>
    </dl>
    <p>
		<input type="submit" value="Submit">
	</p>
</form>

{% if filenames %}
	{% for filename in filenames %}
		<div style="padding:20px;float:left;">
			<img width="500" src="{{ url_for('display_image', filename=filename) }}"> 
		</div>
	{% endfor %}
{% endif %}
</div>
</body>
</html>

Sunday, July 25, 2021

Dynamic Select Box and Sign Up using Python Flask PostgreSQL jsonify and javascript

Dynamic Select Box and Sign Up using Python Flask PostgreSQL jsonify and javascript

install psycopg2 https://pypi.org/project/psycopg2/
Psycopg is the most popular PostgreSQL database adapter for the Python programming language.
(venv) PS C:\flaskmyproject> pip install psycopg2

CREATE TABLE countries (
id serial PRIMARY KEY,
name VARCHAR ( 60 ) NOT NULL
);

INSERT INTO
    countries(id,name)
VALUES
(1, 'Afghanistan'),
(2, 'Aringland Islands'),
(3, 'Albania'),
(4, 'Algeria'),
(171, 'Philippines'),
(227, 'United States of America');

CREATE TABLE state (
id serial PRIMARY KEY,
name VARCHAR ( 60 ) NOT NULL,
country_id INT NOT NULL
);

INSERT INTO state (id, name, country_id) VALUES (1, 'ARMM', 171);
INSERT INTO state (id, name, country_id) VALUES (2, 'Bicol', 171);
INSERT INTO state (id, name, country_id) VALUES (3, 'Central Luzon', 171);
INSERT INTO state (id, name, country_id) VALUES (4, 'Central Mindanao', 171);
INSERT INTO state (id, name, country_id) VALUES (5, 'Alabama', 227);
INSERT INTO state (id, name, country_id) VALUES (6, 'Alaska', 227);
INSERT INTO state (id, name, country_id) VALUES (7, 'Arizona', 227);
INSERT INTO state (id, name, country_id) VALUES (8, 'California', 227);
INSERT INTO state (id, name, country_id) VALUES (9, 'Florida', 227);

CREATE TABLE city (
id serial PRIMARY KEY,
state VARCHAR ( 60 ) NOT NULL,
name VARCHAR ( 60 ) NOT NULL,
stateid INT NOT NULL
);

INSERT INTO city (id, state, name, stateid) VALUES (1, 'CA', 'Anaheim', 8);
INSERT INTO city (id, state, name, stateid) VALUES (2, 'NV', 'Arden-Arcade', 8);
INSERT INTO city (id, state, name, stateid) VALUES (3, 'CA', 'Bakersfield', 8);
INSERT INTO city (id, state, name, stateid) VALUES (4, 'CA', 'Carson', 8);
INSERT INTO city (id, state, name, stateid) VALUES (5, 'NV', 'Daly City', 8);
INSERT INTO city (id, state, name, stateid) VALUES (6, NULL, 'Angeles City', 3);
INSERT INTO city (id, state, name, stateid) VALUES (7, NULL, 'Olongapo', 3);
INSERT INTO city (id, state, name, stateid) VALUES (8, NULL, 'San Fernando', 3);
INSERT INTO city (id, state, name, stateid) VALUES (9, NULL, 'Tarlac', 3);

CREATE TABLE userflask (
id serial PRIMARY KEY,
fullname VARCHAR ( 150 ) NOT NULL,
email VARCHAR ( 150 ) NOT NULL,
countryid INT NOT NULL,
stateid INT NOT NULL,
cityid INT NOT NULL
);
app.py
#app.py
from flask import Flask, render_template, redirect, request, json, jsonify
import psycopg2 #pip install psycopg2 
import psycopg2.extras
      
app = Flask(__name__)
      
app.secret_key = "caircocoders-ednalan"
      
DB_HOST = "localhost"
DB_NAME = "sampledb"
DB_USER = "postgres"
DB_PASS = "admin"
          
conn = psycopg2.connect(dbname=DB_NAME, user=DB_USER, password=DB_PASS, host=DB_HOST)

@app.route('/', methods=['GET', 'POST'])
def index():
    cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    query = "select * from countries"
    cur.execute(query)
    country = cur.fetchall()
    message = ''    
    if request.method == 'POST':
        fullname = request.form['fullname']
        email = request.form['email']
        country = request.form['country']
        state = request.form['state']
        city = request.form['city']
        cur.execute("INSERT INTO userflask (fullname, email, countryid, stateid, cityid) VALUES (%s,%s,%s,%s,%s)",(fullname,email,country,state,city))
        conn.commit()
        cur.close()
        message = "Succesfully Register"
    return render_template('index.html', country=country, message=message)
  
@app.route('/state/<get_state>')
def statebycountry(get_state):
    cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cur.execute("SELECT * FROM state WHERE country_id = %s", [get_state])
    state = cur.fetchall()  
    stateArray = []
    for row in state:
        stateObj = {
                'id': row['id'],
                'name': row['name']}
        stateArray.append(stateObj)
    return jsonify({'statecountry' : stateArray})
   
@app.route('/city/<get_city>')
def city(get_city):
    cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cur.execute("SELECT * FROM city WHERE stateid = %s", [get_city])
    state = cur.fetchall()  
    cityArray = []
    for row in state:
        cityObj = {
                'id': row['id'],
                'name': row['name']}
        cityArray.append(cityObj)
    return jsonify({'citylist' : cityArray})

if __name__ == "__main__":
    app.run(debug=True)
templates/index.html
//templates/index.html
<!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>Dynamic Select Box and Sign Up using Python Flask PostgreSQL jsonify and javascript</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
</head>
<body>
<div class="container">
 <div class="row">
    <div class="col-md-12">
    <p><h2>Dynamic Select Box and Sign Up using Python Flask PostgreSQL jsonify and javascript</h2></p>
    {% if message %}
          <div class="alert alert-success">{{message}}</div>
    {% endif %}
    <form method="POST">
    <div class="form-group">
        <label for="email">Name:</label>
        <input type="text" class="form-control" name="fullname" id="fullname" placeholder="Your Name">
    </div> 
    <div class="form-group">
        <label for="email">Email:</label>
        <input type="email" class="form-control" name="email" id="email" placeholder="Your Email">
    </div>    
    <div class="form-group">
        <label for="email">Country:</label>
        <select class="form-control" id="country" name="country">
            {% for row in country %}
            <option value="{{row.id}}">{{row.name}}</option>
            {% endfor %}
        </select>
    </div>
    <div class="form-group">
        <label for="email">State:</label>
        <select class="form-control" id="state" name="state"></select>
    </div>
    <div class="form-group">
        <label for="email">City:</label>
        <select class="form-control" id="city" name="city"></select>
    </div>
    <input type="submit" class="btn btn-success btn-lg">
  </form> 
   </div>
 </div>
</div> 
<script>
country_select = document.getElementById('country');
state_select = document.getElementById('state');
city_select = document.getElementById('city');
  
country_select.onchange = function(){
 country = country_select.value;
 alert(country);
 fetch('state/' + country).then(function(response){
  response.json().then(function(data) {
   optionHTML = '';
   for (state of data.statecountry) {
    optionHTML += '<option value="' + state.id +'">' + state.name + '</option>'
   }
   state_select.innerHTML = optionHTML;
  });
 });
}
state_select.onchange = function(){
 city = state_select.value; 
 fetch('city/' + city).then(function(response){
  response.json().then(function(data) {
   optionHTML = '';
   for (city_rs of data.citylist) {
    optionHTML += '<option value="' + city_rs.id +'">' + city_rs.name + '</option>'
   }
   city_select.innerHTML = optionHTML;
  });
 });
}
</script>
</body>
</html>

Related Post