article

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

Friday, June 9, 2023

Python Flask Login Register with CRUD Books and Admin LTE Integration

Python Flask Login Register with CRUD Books and Admin LTE Integration

Python Flask 

https://flask.palletsprojects.com/en/2.3.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\myapp\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\myapp>pip install -U Flask-SQLAlchemy

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\myapp>pip install Flask-Bcrypt

C:\flask_dev\myapp\app.py
 
#C:\flask_dev\myapp\app.py
from flask import Flask, render_template, request, redirect, url_for, session
from flask_bcrypt import Bcrypt #pip install Flask-Bcrypt = https://pypi.org/project/Flask-Bcrypt/
from werkzeug.utils import secure_filename
import os

from models import db, Users, Books 
  
app = Flask(__name__)
   
app.config['SECRET_KEY'] = 'cairocoders-ednalan'
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskdb.db'
# Databse configuration mysql                             Username:password@hostname/databasename
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:''@localhost/library-system'
 
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
  
bcrypt = Bcrypt(app) 
 
db.init_app(app)
        
with app.app_context():
    db.create_all()


app.config['UPLOAD_FOLDER'] = 'static/images'
   
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('/register', methods =['GET', 'POST'])
def register():
    mesage = ''
    if request.method == 'POST' and 'name' in request.form and 'password' in request.form and 'email' in request.form :
        fullname = request.form['name']
        password = request.form['password']
        email = request.form['email']
        
        user_exists = Users.query.filter_by(email=email).first() is not None
      
        if user_exists:
            mesage = 'Email already exists !'
        elif not re.match(r'[^@]+@[^@]+\.[^@]+', email):
            mesage = 'Invalid email address !'
        elif not fullname or not password or not email:
            mesage = 'Please fill out the form !'
        else:
            hashed_password = bcrypt.generate_password_hash(password)
            new_user = Users(name=fullname, email=email, password=hashed_password)
            db.session.add(new_user)
            db.session.commit()
            mesage = 'You have successfully registered !'
    elif request.method == 'POST':
        mesage = 'Please fill out the form !'
    return render_template('register.html', mesage = mesage)
    
@app.route('/login', methods =['GET', 'POST'])
def login():
    mesage = ''
    if request.method == 'POST':
        email = request.form['email']
        password = request.form['password']
        #print(email)
        #print(password)
        if email == '' or password == '':
            mesage = 'Please enter email and password !'
        else:
            user = Users.query.filter_by(email=email).first()
            print(user)

            if user is None:
                mesage = 'Please enter correct email / password !' 
            else:
                if not bcrypt.check_password_hash(user.password, password):
                    mesage = 'Please enter correct email and password !'
                else:    
                    session['loggedin'] = True
                    session['userid'] = user.id
                    session['name'] = user.name
                    session['email'] = user.email
                    mesage = 'Logged in successfully !'            
                    return redirect(url_for('dashboard'))

    return render_template('login.html', mesage = mesage)

@app.route("/dashboard", methods =['GET', 'POST'])
def dashboard():
    if 'loggedin' in session:        
        return render_template("dashboard.html")
    return redirect(url_for('login'))   

@app.route('/logout')
def logout():
    session.pop('loggedin', None)
    session.pop('userid', None)
    session.pop('email', None)
    return redirect(url_for('login'))

# Manage Books   
@app.route("/books", methods =['GET', 'POST'])
def books():
    if 'loggedin' in session:
        books = Books.query.all()

        return render_template("books.html", books = books)
    return redirect(url_for('login'))

@app.route('/save_book',methods=['POST'])
def save_book():
    msg = ''    
    if 'loggedin' in session:
        if request.method == 'POST':
            name = request.form['name'] 
            isbn = request.form['isbn']  
            action = request.form['action']

            if action == 'updateBook':
                bookid = request.form['bookid']
                book = Books.query.get(bookid)
            
                book.name = name
                book.isbn = isbn

                db.session.commit()
                print("UPDATE book") 
            else:
                file = request.files['uploadFile']
                filename = secure_filename(file.filename)
                print(filename)
                if file and allowed_file(file.filename):
                    file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
                    filenameimage = file.filename

                    book = Books(name=name, picture=filenameimage, isbn=isbn)
                    db.session.add(book)
                    db.session.commit()
                    print("INSERT INTO book")  
                else:
                    msg  = 'Invalid Uplaod only png, jpg, jpeg, gif' 
            return redirect(url_for('books'))        
        elif request.method == 'POST':
            msg = 'Please fill out the form !'        
        return render_template("books.html", msg = msg)
    return redirect(url_for('login'))

@app.route("/edit_book", methods =['GET', 'POST'])
def edit_book():
    msg = ''    
    if 'loggedin' in session:
        bookid = request.args.get('bookid')
        print(bookid)
        books = Books.query.get(bookid)
        
        return render_template("edit_books.html", books = books)
    return redirect(url_for('login'))

@app.route("/delete_book", methods =['GET'])
def delete_book():
    if 'loggedin' in session:
        bookid = request.args.get('bookid')
        book = Books.query.get(bookid)
        print(book.picture)
        db.session.delete(book)
        db.session.commit()
        os.unlink(os.path.join(app.config['UPLOAD_FOLDER'], book.picture))
        return redirect(url_for('books'))
    return redirect(url_for('login'))   

if __name__=='__main__':
    app.run(debug=True)
C:\flask_dev\myapp\models.py
 
#C:\flask_dev\myapp\models.py
from flask_sqlalchemy import SQLAlchemy
         
db = SQLAlchemy()
         
class Users(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), index=True, unique=True)
    email = db.Column(db.String(150), index=True, unique=True)
    password = db.Column(db.String(255), index=True, unique=True)

class Books(db.Model):
    __tablename__ = "tblbook"
    bookid = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), index=True, unique=True)
    picture = db.Column(db.String(150), index=True, unique=True)
    isbn = db.Column(db.String(255), index=True, unique=True)
Download Bootstrap AdminLTE
https://github.com/ColorlibHQ/AdminLTE/releases
templates/register.html
//
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>AdminLTE 3 | Registration Page</title>

  <!-- Google Font: Source Sans Pro -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
  <!-- Font Awesome -->
  <link rel="stylesheet" href="{{ url_for('static',filename='plugins/fontawesome-free/css/all.min.css') }}">
  <!-- icheck bootstrap -->
  <link rel="stylesheet" href="{{ url_for('static',filename='plugins/icheck-bootstrap/icheck-bootstrap.min.css') }}">
  <!-- Theme style -->
  <link rel="stylesheet" href="{{ url_for('static',filename='css/adminlte.min.css') }}">
</head>
<body class="hold-transition register-page">
<div class="register-box">
  <div class="register-logo">
    <a href="../../index2.html"><b>Admin</b>LTE</a>
  </div>

  <div class="card">
    <div class="card-body register-card-body">
      <p class="login-box-msg">Register a new membership</p>

		<form action="{{ url_for('register') }}" method="post">
        {% if mesage is defined and mesage %}
			<div class="alert alert-warning">{{ mesage }}</div>
		{% endif %}
		
        <div class="input-group mb-3">
          <input type="text" class="form-control" id="name" name="name" placeholder="Full name">
          <div class="input-group-append">
            <div class="input-group-text">
              <span class="fas fa-user"></span>
            </div>
          </div>
        </div>
        <div class="input-group mb-3">
          <input type="email" class="form-control" id="email" name="email" placeholder="Email">
          <div class="input-group-append">
            <div class="input-group-text">
              <span class="fas fa-envelope"></span>
            </div>
          </div>
        </div>
        <div class="input-group mb-3">
          <input type="password" class="form-control" id="password" name="password" placeholder="Password">
          <div class="input-group-append">
            <div class="input-group-text">
              <span class="fas fa-lock"></span>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="col-8">
            <div class="icheck-primary">
              <input type="checkbox" id="agreeTerms" name="terms" value="agree">
              <label for="agreeTerms">
               I agree to the <a href="#">terms</a>
              </label>
            </div>
          </div>
          <!-- /.col -->
          <div class="col-4">
            <button type="submit" class="btn btn-primary btn-block">Register</button>
          </div>
          <!-- /.col -->
        </div>
      </form>

      <div class="social-auth-links text-center">
        <p>- OR -</p>
        <a href="#" class="btn btn-block btn-primary">
          <i class="fab fa-facebook mr-2"></i>
          Sign up using Facebook
        </a>
        <a href="#" class="btn btn-block btn-danger">
          <i class="fab fa-google-plus mr-2"></i>
          Sign up using Google+
        </a>
      </div>

      <a href="{{url_for('login')}}" class="text-center">I already have an account</a> 
    </div>
    <!-- /.form-box -->
  </div><!-- /.card -->
</div>
<!-- /.register-box -->

<!-- jQuery -->
<script src="{{ url_for('static',filename='plugins/jquery/jquery.min.js') }}"></script>
<!-- Bootstrap 4 -->
<script src="{{ url_for('static',filename='plugins/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
<!-- AdminLTE App -->
<script src="{{ url_for('static',filename='js/adminlte.min.js') }}"></script>
</body>
</html>
templates/login.html
//templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>AdminLTE 3 | Log in</title>

  <!-- Google Font: Source Sans Pro -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
  <!-- Font Awesome -->
  <link rel="stylesheet" href="{{ url_for('static',filename='plugins/fontawesome-free/css/all.min.css') }}">
  <!-- icheck bootstrap -->
  <link rel="stylesheet" href="{{ url_for('static',filename='plugins/icheck-bootstrap/icheck-bootstrap.min.css') }}">
  <!-- Theme style -->
  <link rel="stylesheet" href="{{ url_for('static',filename='css/adminlte.min.css') }}">
</head>
<body class="hold-transition login-page">
<div class="login-box">
  <div class="login-logo">
    <a href="../../index2.html"><b>Admin</b>LTE</a>
  </div>
  <!-- /.login-logo -->
  <div class="card">
    <div class="card-body login-card-body">
      <p class="login-box-msg">Sign in to start your session</p>

      <form action="{{ url_for('login') }}" method="post">
        {% if mesage is defined and mesage %}
          <div class="alert alert-warning">{{ mesage }}</div>
        {% endif %}

        <div class="input-group mb-3">
          <input type="email" class="form-control" id="email" name="email" placeholder="Email">
          <div class="input-group-append">
            <div class="input-group-text">
              <span class="fas fa-envelope"></span>
            </div>
          </div>
        </div>
        <div class="input-group mb-3">
          <input type="password" class="form-control" id="password" name="password" placeholder="Password">
          <div class="input-group-append">
            <div class="input-group-text">
              <span class="fas fa-lock"></span>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="col-8">
            <div class="icheck-primary">
              <input type="checkbox" id="remember">
              <label for="remember">
                Remember Me
              </label>
            </div>
          </div>
          <!-- /.col -->
          <div class="col-4">
            <button type="submit" class="btn btn-primary btn-block">Sign In</button>
          </div>
          <!-- /.col -->
        </div>
      </form>

      <div class="social-auth-links text-center mb-3">
        <p>- OR -</p>
        <a href="#" class="btn btn-block btn-primary">
          <i class="fab fa-facebook mr-2"></i> Sign in using Facebook
        </a>
        <a href="#" class="btn btn-block btn-danger">
          <i class="fab fa-google-plus mr-2"></i> Sign in using Google+
        </a>
      </div>
      <!-- /.social-auth-links -->

      <p class="mb-1">
        <a href="forgot-password.html">I forgot my password</a>
      </p>
      <p class="mb-0">
        <a href="{{url_for('register')}}" class="text-center">Register a new account</a>
      </p>
    </div>
    <!-- /.login-card-body -->
  </div>
</div>
<!-- /.login-box -->

<!-- jQuery -->
<script src="{{ url_for('static',filename='plugins/jquery/jquery.min.js') }}"></script>
<!-- Bootstrap 4 -->
<script src="{{ url_for('static',filename='plugins/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
<!-- AdminLTE App -->
<script src="{{ url_for('static',filename='js/adminlte.min.js') }}"></script>
</body>
</html>
templates/dashboard.html
//templates/dashboard.html
{% extends 'layout.html' %}
 
{% block body %}
    <!-- Content Header (Page header) -->
    <div class="content-header">
      <div class="container-fluid">
        <div class="row mb-2">
          <div class="col-sm-6">
            <h1 class="m-0">Dashboard</h1>
          </div><!-- /.col -->
          <div class="col-sm-6">
            <ol class="breadcrumb float-sm-right">
              <li class="breadcrumb-item"><a href="#">Home</a></li>
              <li class="breadcrumb-item active">Dashboard v1</li>
            </ol>
          </div><!-- /.col -->
        </div><!-- /.row -->
      </div><!-- /.container-fluid -->
    </div>
    <!-- /.content-header -->

    <!-- Main content -->
    <section class="content">
      <div class="container-fluid">
        <!-- Small boxes (Stat box) -->
        <div class="row">
          <div class="col-lg-3 col-6">
            <!-- small box -->
            <div class="small-box bg-info">
              <div class="inner">
                <h3>150</h3>

                <p>Total Books</p>
              </div>
              <div class="icon">
                <i class="ion ion-bag"></i>
              </div>
              <a href="#" class="small-box-footer">More info <i class="fas fa-arrow-circle-right"></i></a>
            </div>
          </div>
          <!-- ./col -->
          <div class="col-lg-3 col-6">
            <!-- small box -->
            <div class="small-box bg-success">
              <div class="inner">
                <h3>53<sup style="font-size: 20px">%</sup></h3>

                <p>Available Books</p>
              </div>
              <div class="icon">
                <i class="ion ion-stats-bars"></i>
              </div>
              <a href="#" class="small-box-footer">More info <i class="fas fa-arrow-circle-right"></i></a>
            </div>
          </div>
          <!-- ./col -->
          <div class="col-lg-3 col-6">
            <!-- small box -->
            <div class="small-box bg-warning">
              <div class="inner">
                <h3>44</h3>

                <p>Returned Books</p>
              </div>
              <div class="icon">
                <i class="ion ion-person-add"></i>
              </div>
              <a href="#" class="small-box-footer">More info <i class="fas fa-arrow-circle-right"></i></a>
            </div>
          </div>
          <!-- ./col -->
          <div class="col-lg-3 col-6">
            <!-- small box -->
            <div class="small-box bg-danger">
              <div class="inner">
                <h3>65</h3>

                <p>Issued Books</p>
              </div>
              <div class="icon">
                <i class="ion ion-pie-graph"></i>
              </div>
              <a href="#" class="small-box-footer">More info <i class="fas fa-arrow-circle-right"></i></a>
            </div>
          </div>
          <!-- ./col -->
        </div>
        <!-- /.row -->
        
        <!-- /.row (main row) -->
      </div><!-- /.container-fluid -->
    </section>
    <!-- /.content -->
{% endblock %}
templates/layout.html
//templates/layout.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>AdminLTE 3 | Dashboard</title>

  <!-- Google Font: Source Sans Pro -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
  <!-- Font Awesome -->
  <link rel="stylesheet" href="{{ url_for('static',filename='plugins/fontawesome-free/css/all.min.css') }}">
  <!-- Ionicons -->
  <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
  <!-- iCheck -->
  <link rel="stylesheet" href="{{ url_for('static',filename='plugins/icheck-bootstrap/icheck-bootstrap.min.css') }}">
  <!-- Theme style -->
  <link rel="stylesheet" href="{{ url_for('static',filename='css/adminlte.min.css') }}">
</head>
<body class="hold-transition sidebar-mini layout-fixed">
<div class="wrapper">

  <!-- Preloader -->
  <div class="preloader flex-column justify-content-center align-items-center">
    <img class="animation__shake" src="{{ url_for('static',filename='img/AdminLTELogo.png') }}" alt="AdminLTELogo" height="60" width="60">
  </div>

  <!-- Navbar -->
  <nav class="main-header navbar navbar-expand navbar-white navbar-light">
    <!-- Left navbar links -->
    <ul class="navbar-nav">
      <li class="nav-item">
        <a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars"></i></a>
      </li>
      <li class="nav-item d-none d-sm-inline-block">
        <a href="index3.html" class="nav-link">Home</a>
      </li>
      <li class="nav-item d-none d-sm-inline-block">
        <a href="#" class="nav-link">Contact</a>
      </li>
    </ul>

    <!-- Right navbar links -->
    <ul class="navbar-nav ml-auto">
      <!-- Navbar Search -->
      <li class="nav-item">
        <a class="nav-link" data-widget="navbar-search" href="#" role="button">
          <i class="fas fa-search"></i>
        </a>
        <div class="navbar-search-block">
          <form class="form-inline">
            <div class="input-group input-group-sm">
              <input class="form-control form-control-navbar" type="search" placeholder="Search" aria-label="Search">
              <div class="input-group-append">
                <button class="btn btn-navbar" type="submit">
                  <i class="fas fa-search"></i>
                </button>
                <button class="btn btn-navbar" type="button" data-widget="navbar-search">
                  <i class="fas fa-times"></i>
                </button>
              </div>
            </div>
          </form>
        </div>
      </li>
      <li class="nav-item">
        <a class="nav-link" data-widget="control-sidebar" data-controlsidebar-slide="true" href="#" role="button">
          <i class="fas fa-th-large"></i>
        </a>
      </li>
    </ul>
  </nav>
  <!-- /.navbar -->

  <!-- Main Sidebar Container -->
  <aside class="main-sidebar sidebar-dark-primary elevation-4">
    <!-- Brand Logo -->
    <a href="index3.html" class="brand-link">
      <img src="{{ url_for('static',filename='img/AdminLTELogo.png') }}" alt="AdminLTE Logo" class="brand-image img-circle elevation-3" style="opacity: .8">
      <span class="brand-text font-weight-light">AdminLTE 3</span>
    </a>

    <!-- Sidebar -->
    <div class="sidebar">
      <!-- Sidebar user panel (optional) -->
      <div class="user-panel mt-3 pb-3 mb-3 d-flex">
        <div class="image">
          <img src="{{ url_for('static',filename='img/avatar4.png') }}" class="img-circle elevation-2" alt="User Image">
        </div>
        <div class="info">
          <a href="#" class="d-block">{{session.name}}</a>
        </div>
      </div>

      <!-- SidebarSearch Form -->
      <div class="form-inline">
        <div class="input-group" data-widget="sidebar-search">
          <input class="form-control form-control-sidebar" type="search" placeholder="Search" aria-label="Search">
          <div class="input-group-append">
            <button class="btn btn-sidebar">
              <i class="fas fa-search fa-fw"></i>
            </button>
          </div>
        </div>
      </div>

      <!-- Sidebar Menu -->
      <nav class="mt-2">
        <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
          <!-- Add icons to the links using the .nav-icon class
               with font-awesome or any other icon font library -->
          <li class="nav-item menu-open">
            <a href="{{ url_for('dashboard') }}" class="nav-link active">
              <i class="nav-icon fas fa-tachometer-alt"></i>
              <p>
                Dashboard
                <i class="right fas fa-angle-left"></i>
              </p>
            </a>
          </li>
          <li class="nav-item">
            <a href="{{ url_for('books') }}" class="nav-link">
              <i class="nav-icon fas fa-table"></i>
              <p>
                Manage Books
              </p>
            </a>
          </li>
          <li class="nav-item">
            <a href="{{ url_for('logout') }}" class="nav-link">
              <i class="nav-icon fas fa-th"></i>
              <p>
                Logout
              </p>
            </a>
          </li>
          
        </ul>
      </nav>
      <!-- /.sidebar-menu -->
    </div>
    <!-- /.sidebar -->
  </aside>

  <!-- Content Wrapper. Contains page content -->
  <div class="content-wrapper">
    {% block body %}{% endblock %}
  </div>
  <!-- /.content-wrapper -->
  <footer class="main-footer">
    <strong>Copyright © 2014-2021 <a href="https://adminlte.io">AdminLTE.io</a>.</strong>
    All rights reserved.
    <div class="float-right d-none d-sm-inline-block">
      <b>Version</b> 3.2.0
    </div>
  </footer>

  <!-- Control Sidebar -->
  <aside class="control-sidebar control-sidebar-dark">
    <!-- Control sidebar content goes here -->
  </aside>
  <!-- /.control-sidebar -->
</div>
<!-- ./wrapper -->

<!-- jQuery -->
<script src="{{ url_for('static',filename='plugins/jquery/jquery.min.js') }}"></script>
<!-- Bootstrap 4 -->
<script src="{{ url_for('static',filename='plugins/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
<!-- AdminLTE App -->
<script src="{{ url_for('static',filename='js/adminlte.min.js') }}"></script>
<script>
  $(document).ready(function(){
    $('#addBook').click(function(){ 
      $('#bookModal').modal({
        backdrop: 'static',
        keyboard: false
      });		
      $("#bookModal").on("shown.bs.modal", function () {
        $('#bookForm')[0].reset();				
        $('.modal-title').html("<i class='fa fa-plus'></i> Add book");					
        $('#action').val('addBook');
        $('#save').val('Save');
      });
    });		
  });
  </script>
</body>
</html>
templates/books.html
//templates/books.html
{% extends 'layout.html' %}
 
{% block body %}
    <!-- Content Header (Page header) -->
    <div class="content-header">
      <div class="container-fluid">
        <div class="row mb-2">
          <div class="col-sm-6">
            <h1 class="m-0">Manage Books</h1>
          </div><!-- /.col -->
          <div class="col-sm-6">
            <ol class="breadcrumb float-sm-right">
              <li class="breadcrumb-item"><a href="#">Home</a></li>
              <li class="breadcrumb-item active">Manage Books</li>
            </ol>
          </div><!-- /.col -->
        </div><!-- /.row -->
      </div><!-- /.container-fluid -->
    </div>
    <!-- /.content-header -->

    <!-- Main content -->
    <section class="content">
      <div class="container-fluid">
        <div class="row">
			<h3>Book Listing</h3>
			<br>
			<div class="float-right mb-2 col-md-2">
				<button type="button" id="addBook" class="btn btn-info" title="Add book"><span class="glyphicon glyphicon-plus">Add Book</span></button>
			</div>
			<br><br>			
			<table class="table table-striped">
			<thead>
			  <tr>
				<th></th>
				<th>Book</th>
				<th>ISBN</th>
				<th></th>
				<th></th>
			  </tr>
			</thead>
			<tbody>
				{% for book in books %}			  
					<tr>
					  <td>
					  {% if book.picture %}
						  <img src="../static/images/{{book.picture}}" width="80" height="90">
					  {% else %}
						  <img src="../static/images/default.jpg" width="80" height="90">
					  {% endif %}					
					  </td>
					  <td>{{book.name}}</td>
					  <td>{{book.isbn}}</td>			
					  <td><a href="{{url_for('edit_book', bookid=book.bookid)}}" class="btn btn-primary">Edit</a></td>	
					  <td><a href="{{url_for('delete_book', bookid=book.bookid)}}" class="btn btn-danger">Delete</a></td>
					</tr> 
			  {% endfor %}	  
			  </tbody>
		  </table>	
        </div>
      </div><!-- /.container-fluid -->
    </section>
    <!-- /.content -->
	<div class="modal fade" id="bookModal">
        <div class="modal-dialog">
			<form method="post" id="bookForm" action="{{ url_for('save_book')}}" enctype="multipart/form-data">
			<div class="modal-content">
				<div class="modal-header">
				<h4 class="modal-title">Add New</h4>
				<button type="button" class="close" data-dismiss="modal" aria-label="Close">
					<span aria-hidden="true">×</span>
				</button>
				</div>
				<div class="modal-body">
					<div class="form-group">							
						<label for="book" class="control-label">Book</label>							
						<input type="text" name="name" id="name" autocomplete="off" class="form-control" placeholder="book name"/>
										
					</div>
					<div class="form-group">							
						<label for="book" class="control-label">ISBN No</label>							
						<input type="text" name="isbn" id="isbn" autocomplete="off" class="form-control" placeholder="isbn name"/>		
					</div>
					<div class="form-group">
						<label>File Upload</label>
						<input type="file" name="uploadFile" accept=".jpg, .png" />
					</div>

				</div>
				<div class="modal-footer justify-content-between">
				<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
				<input type="hidden" name="action" id="action" value="" />
				<input type="submit" name="save" id="save" class="btn btn-primary" value="Save changes" />
				</div>
			</div>
			</form>
          <!-- /.modal-content -->
        </div>
        <!-- /.modal-dialog -->
    </div>
{% endblock %}
templates/books.html
//templates/books.html
{% extends 'layout.html' %}
 
{% block body %}
    <!-- Content Header (Page header) -->
    <div class="content-header">
      <div class="container-fluid">
        <div class="row mb-2">
          <div class="col-sm-6">
            <h1 class="m-0">Manage Books</h1>
          </div><!-- /.col -->
          <div class="col-sm-6">
            <ol class="breadcrumb float-sm-right">
              <li class="breadcrumb-item"><a href="#">Home</a></li>
              <li class="breadcrumb-item active">Manage Books</li>
            </ol>
          </div><!-- /.col -->
        </div><!-- /.row -->
      </div><!-- /.container-fluid -->
    </div>
    <!-- /.content-header -->

    <!-- Main content -->
    <section class="content">
      <div class="container-fluid">
        <div class="row">
            <div class="col-md-12">
			<h3>Book Edit</h3>
            <form method="post" id="bookForm" action="{{ url_for('save_book')}}">
                <div class="card-body">               
                                       
                        <div class="form-group">							
                            <label for="book" class="control-label">Book</label>							
                            <input type="text" name="name" id="name" autocomplete="off" class="form-control" placeholder="book name" value="{{books.name}}"/>                             
                        </div>                    
                        <div class="form-group">							
                            <label for="book" class="control-label">ISBN No</label>							
                            <input type="text" name="isbn" id="isbn" autocomplete="off" class="form-control" placeholder="isbn name" value="{{books.isbn}}"/>                                        
                        </div>    
                        <div class="form-group">							
                            <label for="book" class="control-label">Picture</label>							
                            <img src="static/images/{{books.picture}}" width="360"/>
                        </div>                               
                        
                        <input type="hidden" name="bookid" id="bookid" value="{{books.bookid}}" />									
                        <input type="hidden" name="action" id="action" value="updateBook" />
                        <input type="submit" name="save" id="save" class="btn btn-info" value="Save" />                    
                </div>
            </form>
            </div>
        </div>
      </div><!-- /.container-fluid -->
    </section>
{% endblock %}
templates/edit_books.html
//templates/edit_books.html
{% extends 'layout.html' %}
 
{% block body %}
    <!-- Content Header (Page header) -->
    <div class="content-header">
      <div class="container-fluid">
        <div class="row mb-2">
          <div class="col-sm-6">
            <h1 class="m-0">Manage Books</h1>
          </div><!-- /.col -->
          <div class="col-sm-6">
            <ol class="breadcrumb float-sm-right">
              <li class="breadcrumb-item"><a href="#">Home</a></li>
              <li class="breadcrumb-item active">Manage Books</li>
            </ol>
          </div><!-- /.col -->
        </div><!-- /.row -->
      </div><!-- /.container-fluid -->
    </div>
    <!-- /.content-header -->

    <!-- Main content -->
    <section class="content">
      <div class="container-fluid">
        <div class="row">
            <div class="col-md-12">
			<h3>Book Edit</h3>
            <form method="post" id="bookForm" action="{{ url_for('save_book')}}">
                <div class="card-body">               
                                       
                        <div class="form-group">							
                            <label for="book" class="control-label">Book</label>							
                            <input type="text" name="name" id="name" autocomplete="off" class="form-control" placeholder="book name" value="{{books.name}}"/>                             
                        </div>                    
                        <div class="form-group">							
                            <label for="book" class="control-label">ISBN No</label>							
                            <input type="text" name="isbn" id="isbn" autocomplete="off" class="form-control" placeholder="isbn name" value="{{books.isbn}}"/>                                        
                        </div>    
                        <div class="form-group">							
                            <label for="book" class="control-label">Picture</label>							
                            <img src="static/images/{{books.picture}}" width="360"/>
                        </div>                               
                        
                        <input type="hidden" name="bookid" id="bookid" value="{{books.bookid}}" />									
                        <input type="hidden" name="action" id="action" value="updateBook" />
                        <input type="submit" name="save" id="save" class="btn btn-info" value="Save" />                    
                </div>
            </form>
            </div>
        </div>
      </div><!-- /.container-fluid -->
    </section>
{% endblock %}
run (venv) C:\flask_dev\flaskreact>flask run

Thursday, June 8, 2023

Python Flask YouTube video Downloader

Python Flask YouTube video Downloader

Python Flask 

https://flask.palletsprojects.com/en/2.3.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

Install requirements

pytube
pytube is a genuine, lightweight, dependency-free Python library (and command-line utility) for downloading YouTube videos.
https://pypi.org/project/pytube/

(venv) PS C:\flask_dev\myapp>pip install pytube

pathlib
pathlib offers a set of classes to handle filesystem paths. It offers the following advantages over using string objects:
https://pypi.org/project/pathlib/

(venv) PS C:\flask_dev\myapp>pip install pathlib

C:\flask_dev\myapp\app.py
 
#
from flask import Flask, request, render_template
from pytube import YouTube #pip install pytube https://pypi.org/project/pytube/
from pathlib import Path #pip install pathlib https://pypi.org/project/pathlib/
import os
import re

app = Flask(__name__)

@app.route("/download", methods=["GET","POST"])
def downloadVideo():      
    mesage = ''
    errorType = 0
    if request.method == 'POST' and 'video_url' in request.form:
        youtubeUrl = request.form["video_url"]
        if(youtubeUrl):
            validateVideoUrl = (
            r'(https?://)?(www\.)?'
            '(youtube|youtu|youtube-nocookie)\.(com|be)/'
            '(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')
            validVideoUrl = re.match(validateVideoUrl, youtubeUrl)
            if validVideoUrl:
                url = YouTube(youtubeUrl)
                video = url.streams.get_highest_resolution()
                downloadFolder = str(os.path.join(Path.home(), "Downloads/Youtube_download"))
                video.download(downloadFolder)
                mesage = 'Video Downloaded Successfully!'
                errorType = 1
            else:
                mesage = 'Enter Valid YouTube Video URL!'
                errorType = 0
        else:
            mesage = 'Enter YouTube Video Url.'
            errorType = 0            
    return render_template('youtube.html', mesage = mesage, errorType = errorType) 

if __name__ == "__main__":
    app.run()
templates/youtube.html
 
#templates/youtube.html
<html>
<head>
    <Title>Python Flask YouTube video Downloader</Title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>    
    <div class="container mt-3">
        <h2>Python Flask YouTube Downloader</h2>
        <form action="/download" method="post">
            {% if mesage is defined and mesage %}
                {% if errorType is defined and errorType %}
                    <div class="alert alert-success">{{ mesage }}</div>
                {% else  %}
                    <div class="alert alert-danger">{{ mesage }}</div>
                {% endif %}
            {% endif %}
            <div class="mb-3 mt-3">
                <label for="video_url">Enter YouTube Video Url:</label>
                <input type="text" class="form-control" id="video_url" placeholder="Enter url" name="video_url">
            </div>          
            <button type="submit" class="btn btn-primary">Download</button>
        </form>
      </div>
    <br><br>
</body>
</html>
run (venv) C:\flask_dev\myapp>flask run
http://127.0.0.1:5000/download

Tuesday, May 30, 2023

React JS Python Flask REST API CRUD (Create, Read, Update and Delete) | Axios Mysql

React JS Python Flask REST API CRUD (Create, Read, Update and Delete) | Axios Mysql

Python Flask 

https://flask.palletsprojects.com/en/2.3.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-Cors
A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.
https://pypi.org/project/Flask-Cors/

(venv) PS C:\flask_dev\flaskreact>pip install -U flask-cors

C:\flask_dev\flaskreact\app.py

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

app = Flask(__name__)

app.config['SECRET_KEY'] = 'cairocoders-ednalan'
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskdb.db'
# Databse configuration mysql                             Username:password@hostname/databasename
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:''@localhost/flaskreact'

SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
 
CORS(app, supports_credentials=True)

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

ma=Marshmallow(app)

class UserSchema(ma.Schema):
    class Meta:
        fields = ('id','name','email','password')
 
user_schema = UserSchema()
users_schema = UserSchema(many=True)
 
@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

@app.route('/users', 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('/newuser',methods=['POST'])
def newuser():
    name = request.json['name']
    email = request.json['email']
    password = request.json['password']
 
    print(name)
    print(email)
    print(password)

    users = Users(name=name, email=email, password=password)

    db.session.add(users)
    db.session.commit()
    return user_schema.jsonify(users)

if __name__ == "__main__":
    app.run(debug=True)
C:\flask_dev\flaskreact\models.py
#C:\flask_dev\flaskreact\models.py
from flask_sqlalchemy import SQLAlchemy
        
db = SQLAlchemy()
        
class Users(db.Model):
    __tablename__ = "tblusers"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), index=True, unique=True)
    email = db.Column(db.String(150), index=True, unique=True)
    password = db.Column(db.String(255), index=True, unique=True)
run (venv) C:\flask_dev\flaskreact>flask run

get all user
http://127.0.0.1:5000/users

get info
http://127.0.0.1:5000/userdetails/1

put update data
http://127.0.0.1:5000/userupdate/1

delete data
http://127.0.0.1:5000/userdelete/1

post add new
http://127.0.0.1:5000/newuser

json
{
"name":"cairocoders ednalan",
"email":"cairocoders@gmail.com",
"password":"123456"
}

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 Home from "./components/Home";
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import View from "./components/View";
import Edit from "./components/Edit";

function App() {
  return (
    <div className="App">
        <Router>
            <Routes>
              <Route exact path="/" element={<Home/>}/>
              <Route exact path="/view/:id" element={<View/>}/>
              <Route exact path="/edit/:id" element={<Edit/>}/> 
            </Routes>
        </Router>
	</div>
  );
}

export default App;
https://github.com/axios/axios

Installing the Axios Client

$ npm install axios
C:\reactdev\myreactdev>npm install axios

Install React Router Dom
https://www.npmjs.com/package/react-router-dom
C:\react-js\myreactdev>npm i react-router-dom --save

C:\react-js\myreactdev\src\components\Home.js
//C:\react-js\myreactdev\src\components\Home.js
import React, { useState } from 'react';
import List from './List';
import axios from 'axios';

const Home = () => {

    const [userField, setUserField] = useState({
        name: "",
        email: "",
        password: ""
    });

    const changeUserFieldHandler = (e) => {
        setUserField({
            ...userField,
            [e.target.name]: e.target.value
        });
        //console.log(userField);

    }
    const [loading,setLoading]=useState()

    const onSubmitChange = async (e) => {
        e.preventDefault();
        try {
            const responce= await axios.post("http://127.0.0.1:5000/newuser", userField);
			console.log(responce)
            setLoading(true);
        } catch (err) {
            console.log("Something Wrong");
        }
    }
    if(loading){
        return <Home/>
    }

    return (
        <div className="container">
            <h2 className='w-100 d-flex justify-content-center p-3'>React JS Laravel 10 REST API CRUD (Create, Read, Update and Delete) | Axios Mysql</h2>
                <div className='row'>
                    <div className='col-md-4'>
                        <h3>Add Your Detail</h3>
                        <form>
                            <div className="mb-3 mt-3">
                                <label className="form-label"> Full Name:</label>
                                <input type="text" className="form-control" id="name" placeholder="Enter Your Full Name" name="name" onChange={e => changeUserFieldHandler(e)} />
                            </div>
                            <div className="mb-3 mt-3">
                                <label className="form-label">Email:</label>
                                <input type="email" className="form-control" id="email" placeholder="Enter email" name="email" onChange={e => changeUserFieldHandler(e)} required/>
                            </div>
                            <div className="mb-3 mt-3">
                                <label className="form-label">Password:</label>
                                <input type="text" className="form-control" id="password" placeholder="Enter password" name="password" onChange={e => changeUserFieldHandler(e)} required/>
                            </div>
							
                            <button type="submit" className="btn btn-primary" onClick={e => onSubmitChange(e)}>Add User</button>
                        </form>
                    </div>
                    <div className='col-md-8'>
                        <List />
                    </div>
                </div>
        </div>
    )
};

export default Home;
C:\react-js\myreactdev\src\components\List.js
//C:\react-js\myreactdev\src\components\List.js
import React, { useState, useEffect } from 'react';
import { NavLink } from 'react-router-dom';
import axios from 'axios'


const List = () => {
    const [userData, setUSerData] = useState([]);
    useEffect(() => {
        fetchData();
    }, [])

    const fetchData = async () => {
        try {
            const result = await axios("http://127.0.0.1:5000/users");
            //console.log(result.data);
            setUSerData(result.data)
        } catch (err) {
            console.log("somthing Wrong");
        }
    }

    const handleDelete=async(id)=>{
		console.log(id);
        await axios.delete("http://127.0.0.1:5000/userdelete/"+id);
        const newUserData=userData.filter((item)=>{
            return(
                item.id !==id
            )
        })
        setUSerData(newUserData);
    }

    return(
		<div className="container">
        <h3>User Details</h3>
        <table className="table table-bordered">
            <thead>
                <tr>
                    <th>S No.</th>
                    <th>Full Name</th>
                    <th>Email</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                {
                    userData.map((user, i) => {
                        return (
                            <tr key={i}>
                                <td>{i + 1}</td>
                                <td>{user.name} </td>
                                <td>{user.email} </td>
                                <td>
									<NavLink to={`/view/${user.id}`} className="btn btn-success mx-2">View</NavLink>
									<NavLink to={`/edit/${user.id}`} className="btn btn-info mx-2">Edit</NavLink>
									<button onClick={()=>handleDelete(user.id)} className="btn btn-danger">Delete</button>
								</td>
                            </tr>
                        )
                    })
                }

            </tbody>
        </table>
		</div>
	);
};

export default List;
C:\react-js\myreactdev\src\components\View.js
//C:\react-js\myreactdev\src\components\View.js
import axios from 'axios';
import React, { useState, useEffect } from 'react';
import { useParams,useNavigate } from 'react-router-dom';

const View = () => {
    const {id}=useParams();
    // console.log(id);
    const[user,setUser]=useState([]);
	const navigate = useNavigate();

    useEffect(()=>{
        fetchUser();
    },[id]);

    const fetchUser=async()=>{
        try{
        const result=await axios.get("http://127.0.0.1:5000/userdetails/"+id);
        console.log(result.data);
        setUser(result.data)

        }catch(err){
            console.log("Something Wrong");
        }
    }

    const clickToBackHandler=()=>{
		navigate('/');
    }

    return <div>
        <div className="container">
            <div className='row'>
                <div className='col-md-12'>

                    <h1>User Details</h1>
                    <table className="table">
                        <thead>
                            <tr>
                                <th>S No.</th>
                                <th>Full Name</th>
                                <th>Email</th>
                              
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>{user.id}</td>
                                <td>{user.name}</td>
                                <td>{user.email}</td>
                            </tr>

                        </tbody>
                    </table>
                </div>

            </div>
        </div>
        <div className='container d-flex justify-content-center'>
            <div><button className='btn btn-primary' onClick={clickToBackHandler}>Back To Home</button></div>
        </div>
    </div>;
};

export default View;
C:\react-js\myreactdev\src\components\Edit.js
//C:\react-js\myreactdev\src\components\Edit.js
import React,{ useState, useEffect } from 'react';
import axios from 'axios';
import { useNavigate ,useParams } from 'react-router-dom';

const Edit = () => {
    const {id}=useParams()
	const navigate = useNavigate();
    const clickToBackHandler=()=>{
		navigate('/');
    }

    const [userField, setUserField] = useState({
        name: "",
        email: ""
    });

    useEffect(()=>{
        fetchUser();
    },[id])

    const fetchUser=async()=>{
        try{
			const result=await axios.get("http://127.0.0.1:5000/userdetails/"+id);
			// console.log(result.data);
			setUserField(result.data)
        }catch(err){
            console.log("Something Wrong");
        }
    }

    const changeUserFieldHandler = (e) => {
        setUserField({
            ...userField,
            [e.target.name]: e.target.value
        });
        console.log(userField);
    }
    
    const onSubmitChange = async (e) => {
        e.preventDefault();
        try {
            await axios.put("http://127.0.0.1:5000/userupdate/"+id, userField);
			navigate('/');	
        } catch (err) {
            console.log("Something Wrong");
        }
    }

    return(
		<div className="container">
			<h1>Edit Form</h1>
			<form>
				<div className="mb-3 mt-3">
					<label className="form-label"> ID:</label>
					<input type="text" className="form-control" id="id" name="id" value={id} disabled />
				</div>
				<div className="mb-3 mt-3">
					<label className="form-label"> Full Name:</label>
					<input type="text" className="form-control" placeholder="Enter Your Full Name" name="name" value={userField.name} onChange={e => changeUserFieldHandler(e)} />
				</div>
				<div className="mb-3 mt-3">
					<label className="form-label">Email:</label>
					<input type="email" className="form-control" id="email" placeholder="Enter email" name="email" value={userField.email}  onChange={e => changeUserFieldHandler(e)}/>
				</div>
                <div className="mb-3 mt-3">
                     <label className="form-label">Password:</label>
                      <input type="text" className="form-control" id="password" placeholder="Enter password" name="password" onChange={e => changeUserFieldHandler(e)} required/>
                </div>
				<button type="submit" className="btn btn-primary" onClick={e=>onSubmitChange(e)}>Update</button>
			</form>
			<div className='container d-flex justify-content-center'>
				<button className='btn btn-primary' onClick={ clickToBackHandler}>Back To Home</button>
			</div>
		</div>
	);
};

export default Edit;
react-js\myreactdev\public\index.html
//react-js\myreactdev\public\index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
Run C:\react-j\myreactdev>npm start
http://localhost:3000/

Sunday, May 28, 2023

React JS Python Flask Search Bar | Filter Search

React JS Python Flask Search Bar | Filter Search

Python Flask 

https://flask.palletsprojects.com/en/2.3.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-Cors
A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.
https://pypi.org/project/Flask-Cors/

(venv) PS C:\flask_dev\flaskreact>pip install -U flask-cors

C:\flask_dev\flaskreact\app.py

#C:\flask_dev\flaskreact\app.py
from flask import Flask, jsonify
from flask_cors import CORS, cross_origin #ModuleNotFoundError: No module named 'flask_cors' = pip install Flask-Cors
from models import db, Users

app = Flask(__name__)
   
app.config['SECRET_KEY'] = 'cairocoders-ednalan'
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskdb.db'
# Databse configuration mysql                             Username:password@hostname/databasename
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:''@localhost/flaskreact'
   
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
   
CORS(app, supports_credentials=True)

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

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

@app.route('/users', methods=['GET']) 
def users():
         
    total = Users.query.count()
     
    userdata = Users.query.order_by(Users.id.asc()).all()  
     
    return jsonify({
        'total': total,
        'results': [{
            'id': rs.id,
            'name': rs.name,
            'email': rs.email,
            'password': rs.password
        } for rs in userdata]
    })
   
if __name__ == "__main__":
    app.run(debug=True)
C:\flask_dev\flaskreact\models.py
#C:\flask_dev\flaskreact\models.py
from flask_sqlalchemy import SQLAlchemy
       
db = SQLAlchemy()
       
class Users(db.Model):
    __tablename__ = "tblusers"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), index=True, unique=True)
    email = db.Column(db.String(150), index=True, unique=True)
    password = db.Column(db.String(255), index=True, unique=True)
run (venv) C:\flask_dev\flaskreact>flask run
http://127.0.0.1:5000/users

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
//
import React, { useEffect, useState } from "react";
import "./App.css";

import SearchBar from "./Component/SearchBar";
//import allUsers from "./Data.json";

function App() {
	
	  const [allUsers, setAllcountry] = useState([]);
	
    useEffect(() => {
      const getusers = async () => {
        const getres = await fetch("http://127.0.0.1:5000/users");
        const setusers = await getres.json();
        //console.log(setusers.results);
        setAllcountry(await setusers.results);
      };
      getusers();
    }, []);
  
    return (
      <div className="App">
        <SearchBar placeholder="Enter a Name..." data={allUsers} />
      </div>
    );
}

export default App;
C:\react-js\myreactdev\src\Component\SearchBar.js
//C:\react-js\myreactdev\src\Component\SearchBar.js
import React, { useState } from "react";

function SearchBar({ placeholder, data }) {
  const [filteredData, setFilteredData] = useState([]);
  const [wordEntered, setWordEntered] = useState("");
	//console.log(data);
	
  const handleFilter = (event) => {
      const searchWord = event.target.value;
      setWordEntered(searchWord);
      const newFilter = data.filter((value) => {
        return value.name.toLowerCase().includes(searchWord.toLowerCase());
      });
      //console.log(searchWord);
      if (searchWord === "") {
        setFilteredData([]);
      } else {
        setFilteredData(newFilter);
      }
    };

  return (
        <div className="row d-flex justify-content-center ">
            <div className="col-md-6">
                <div className="form">
                <i className="fa fa-search"></i>
                <input
                  type="text"
                  placeholder={placeholder}
                  className="form-control form-input"
                  value={wordEntered}
                  onChange={handleFilter}
                />
                <span className="left-pan"><i className="fa fa-microphone"></i></span>
                </div>

				{filteredData.length !== 0 && (
					<div className="dataResult">
					  {filteredData.slice(0, 15).map((value, index) => {
						return (
						<div className="list border-bottom" key={index}>
							<div className="d-flex flex-column ml-3">
							  <span>{value.name}</span>
							</div>                   
						</div>
						);
					  })}
					</div>
				)}
				  
              </div>
        </div>
  );
}

export default SearchBar;
C:\react-js\myreactdev\src\Data.json
//C:\react-js\myreactdev\src\Data.json
[
	{
		"id":1,
		"name":"Cairocoders Ednalan",
		"email":"cairocoders@gmail.com"
	},
	{
		"id":2,
		"name":"clydey Ednalan",
		"email":"clydey@gmail.com"
	}
]
react-js\myreactdev\public\index.html
//react-js\myreactdev\public\index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"/>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
C:\react-js\myreactdev\src\App.css
//C:\react-js\myreactdev\src\App.css
body{
    background: #d1d5db;
}
.height{
    height: 100vh;
}
.form{
	margin-bottom:10px;margin-top:50px;
    position: relative;
}
.form .fa-search{
    position: absolute;
    top:20px;
    left: 20px;
    color: #9ca3af;
}
.form span{
    position: absolute;
    right: 17px;
    top: 13px;
    padding: 2px;
    border-left: 1px solid #d1d5db;

}
.left-pan{
    padding-left: 7px;
}
.left-pan i{
   padding-left: 10px;
}
.form-input{
    height: 55px;
    text-indent: 33px;
    border-radius: 10px;
}
.form-input:focus{
    box-shadow: none;
    border:none;
}

.list{
  background-color:#ffffff;	
  padding-top: 20px;padding-left:20px;
  padding-bottom: 10px;
  display: flex;
  align-items: center;
}
.border-bottom{
  border-bottom: 2px solid #eee;
}
Run C:\react-j\myreactdev>npm start
http://localhost:3000/

Wednesday, May 17, 2023

React js Python Flask Mysql Show Product List with pagination Next Prev

React js Python Flask Mysql Show Product List with pagination Next Prev

Python Flask 

https://flask.palletsprojects.com/en/2.3.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-Cors
A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.
https://pypi.org/project/Flask-Cors/

(venv) PS C:\flask_dev\flaskreact>pip install -U flask-cors

C:\flask_dev\flaskreact\app.py

 
#C:\flask_dev\flaskreact\app.py
from flask import Flask, request, jsonify
from flask_cors import CORS, cross_origin #ModuleNotFoundError: No module named 'flask_cors' = pip install Flask-Cors
  
from models import db, Products
  
app = Flask(__name__)
  
app.config['SECRET_KEY'] = 'cairocoders-ednalan'
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskdb.db'
# Databse configuration mysql                             Username:password@hostname/databasename
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:''@localhost/flaskreact'
  
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
  
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('/products/<int:page>/<int:per_page>', methods=['GET']) #http://127.0.0.1:5000/products/1/4
def products(page=1, per_page=4):
   
    nextpage = page + 1
    prevpage = page - 1
        
    total = Products.query.count()
    
    productdata = Products.query.order_by(Products.id.asc())  
    products = productdata.paginate(page=page, per_page=per_page)
    
    #print(products.next_num)
    #print(products.prev_num)
    
    nextnumber = products.next_num
    if nextnumber == None:
        next_page_url = ""
    else:
        next_page_url = f"http://127.0.0.1:5000/products/{nextpage}/{per_page}"
       
    prev_number = products.prev_num
    if prev_number == None:
        prev_page = ""
    else:
        prev_page = f"http://127.0.0.1:5000/products/{prevpage}/{per_page}"
        
    return jsonify({
        'total': total,
        'next_page_url': next_page_url,
        'prev_page_url': prev_page,
        'results': [{
            'id': rs.id,
            'name': rs.name,
            'image': rs.image,
            'description': rs.description
        } for rs in products.items]
    })
  
if __name__ == "__main__":
    app.run(debug=True)
C:\flask_dev\flaskreact\models.py
 
#C:\flask_dev\flaskreact\models.py
from flask_sqlalchemy import SQLAlchemy
      
db = SQLAlchemy()
      
class Products(db.Model):
    __tablename__ = "products"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), index=True, unique=True)
    image = db.Column(db.String(150), index=True, unique=True)
    description = db.Column(db.String(255), index=True, unique=True)
run (venv) C:\flask_dev\flaskreact>flask run
http://127.0.0.1:5000/products/1/4

Database Table

CREATE TABLE `products` (
`id` bigint(20) UNSIGNED NOT NULL,
`name` varchar(255) NOT NULL,
`image` varchar(255) NOT NULL,
`description` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `products` (`id`, `name`, `image`, `description`) VALUES
(1, 'Asus Vivobook 14', '1.jpg', 'Asus Vivobook 14\" AMD Ryzen 3 3250 8gb/128gb M415DA-R3128 Slate [Grey]'),
(2, 'Acer Aspire 5 15.6', '2.jpg', 'Acer Aspire 5 15.6” laptop Ryzen 5-5500U 8GB RAM 512GB SSD - Silver'),
(3, 'Lenovo laptop t440', '3.jpg', 'Lenovo laptop t440 t450 t460 t470s i5 i7 5th gen 7th gen laptop built in camera for online class'),
(4, 'HP 3.0 2TB Flash Drive Metal', '4.jpg', 'HP 3.0 2TB Flash Drive Metal Waterproof High speed U Disk Flash Drive '),
(5, 'Desk Mat Laptop Mat Pad Gaming', '5.jpg', 'Desk Mat Laptop Mat Pad Gaming Large Mouse Pad Long Mousepad Leatherette Waterproof'),
(6, 'XIAOMI Original OTG metal pendrive 2TB', '6.jpg', 'XIAOMI Original OTG metal pendrive 2TB'),
(7, 'Monsy D103 Laptop Stand Aluminum Alloy', '7.jpg', 'Monsy D103 Laptop Stand Aluminum Alloy'),
(8, 'HD Webcam Web Camera', '8.jpg', 'HD Webcam Web Camera'),
(9, '300Mbps Wireless-N WiFi Repeater ', '9.jpg', '300Mbps Wireless-N WiFi Repeater '),
(10, 'Mumu 6033 Unisex 15.6 Inch Laptop', '10.jpg', 'Mumu 6033 Unisex 15.6 Inch Laptop Usb Backpack Anti Theft Men Bag Travel Male Leisure Bags'),
(11, 'Mini Computer Speakers Stereo USB Wired Powered for PC/Laptops/Smartphone', '11.jpg', 'Mini Computer Speakers Stereo USB Wired Powered for PC/Laptops/Smartphone');

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

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

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

https://github.com/axios/axios

Installing the Axios Client
$ npm install axios

C:\reactdev\myreactdev>npm install axios
C:\react-js\myreactdev\src\App.js

//C:\react-js\myreactdev\src\App.js
import React, { useEffect, useState } from "react";
import axios from "axios";
// Component
import Navbar from "./Component/Navbar";
import ProductList from "./Component/ProductList";
 
function App() {
  const [products, setProducts] = useState([]);
  const [info, setInfo] = useState({});
  
  const url = "http://127.0.0.1:5000/products/1/4";
 
  const fetchProducts = (url) => {
    axios
      .get(url)
      .then((data) => {
        setProducts(data.data.results);
        //console.log(data.data.results);
        setInfo(data.data);
        //console.log(data.data);
      })
      .catch((error) => {
        console.log(error);
      });
  };
   
  const handleNextPage = () => {
    fetchProducts(info.next_page_url);
    window.scrollTo(0, 0);
  };
  
  const handlePreviousPage = () => {
    fetchProducts(info.prev_page_url);
    window.scrollTo(0, 0);
  };
  
  useEffect(() => {
    fetchProducts(url);
  }, []);
 
 
  return (
    <>
      <Navbar brand="Cairocoders" />
 
      <div className="container py-5"><p><h2>React js Python Flask Mysql Show Product List with pagination Next Prev</h2></p>
        <nav>
  
          <ul className="pagination justify-content-center">
            {info.prev_page_url ? (
              <li className="page-item">
                <button className="page-link" onClick={handlePreviousPage}>
                  Previous
                </button>
              </li>
            ) : null}
            {info.next_page_url ? (
              <li className="page-item">
                <button className="page-link" onClick={handleNextPage}>
                  Next
                </button>
              </li>
            ) : null}
          </ul>
  
        </nav>
      </div>
       
      <ProductList products={products} />
       
      <div className="container pb-5">
        <nav>
          <ul className="pagination justify-content-center">
            {info.prev_page_url ? (
              <li className="page-item">
                <button className="page-link" onClick={handlePreviousPage}>
                  Previous
                </button>
              </li>
            ) : null}
            {info.next_page_url ? (
              <li className="page-item">
                <button className="page-link" onClick={handleNextPage}>
                  Next
                </button>
              </li>
            ) : null}
          </ul>
        </nav>
      </div>
	  
    </>
  );
}
 
export default App;
C:\react-js\myreactdev\src\Component\Navbar.js
//C:\react-js\myreactdev\src\Component\Navbar.js
import React from "react";
 
const Navbar = ({ brand }) => {
  return (
    <nav className="navbar navbar-dark bg-dark">
      <div className="container">
        <a className="navbar-brand text-uppercase" href="/">
          {brand}
        </a>
      </div>
    </nav>
  );
};
 
export default Navbar;
C:\react-js\myreactdev\src\Component\ProductList.js
//C:\react-js\myreactdev\src\Component\ProductList.js
import React from "react";
 
const ProductList = ({ products }) => {
  return (
    <div className="container">
      <div className="row">
        {products.map((item, index) => (
          <div key={index} className="col-lg-3 col-md-6 col-sm-12 mb-4">
            <div className="card" style={{ minWidth: "200px" }}>
                <img src={`http://127.0.0.1:5000/static/${item.image}`} alt="Product list" className="card-img-top" />
              <div className="card-body">
                <h5 className="card-title">{item.name}</h5>
                <hr />
                <p className="card-text">Description: {item.description}</p>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};
 
export default ProductList;
react-js\myreactdev\public\index.html
//react-js\myreactdev\public\index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
Run C:\react-j\myreactdev>npm start
http://localhost:3000/

Thursday, April 27, 2023

ReactJs Python Flask Dynamic Select Country State City | Axios Mysql

ReactJs Python Flask Dynamic Select Country State City | Axios Mysql

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

Flask-Cors
A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.
https://pypi.org/project/Flask-Cors/

(venv) PS C:\flask_dev\flaskreact>pip install -U flask-cors

C:\flask_dev\flaskreact\app.py

 
#C:\flask_dev\flaskreact\app.py
from flask import Flask, jsonify
from flask_cors import CORS #ModuleNotFoundError: No module named 'flask_cors' = pip install Flask-Cors
from flask_marshmallow import Marshmallow #ModuleNotFoundError: No module named 'flask_marshmallow' = pip install flask-marshmallow https://pypi.org/project/flask-marshmallow/
  
from models import db, Countries, State, City
  
app = Flask(__name__)
CORS(app, supports_credentials=True)
  
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskdb.db'
# Databse configuration mysql                             Username:password@hostname/databasename
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:''@localhost/flaskreact'
  
db.init_app(app)
    
with app.app_context():
    db.create_all()
  
ma=Marshmallow(app)
   
class CountriesSchema(ma.Schema):
    class Meta:
        fields = ('ID','countryName')

class StateSchema(ma.Schema):
    class Meta:
        fields = ('id','name','country_id')

class CitySchema(ma.Schema):
    class Meta:
        fields = ('id','name','stateid')

countries_schema = CountriesSchema(many=True)
state_schema = StateSchema(many=True)
city_schema = CitySchema(many=True)

@app.route("/")
def hello_world():
    return "Hello, World!"
  
@app.route('/listall',methods =['GET'])
def listall():
    all_countries = Countries.query.all()
    results = countries_schema.dump(all_countries)
    return jsonify(results)

@app.route('/state/<get_state>')
def statebycountry(get_state):
    state = State.query.filter_by(country_id=get_state).all()
    results = state_schema.dump(state)
    return jsonify(results)

@app.route('/city/<get_city>')
def city(get_city):
    city_data = City.query.filter_by(stateid=get_city).all()
    results = city_schema.dump(city_data)
    return jsonify(results)
C:\flask_dev\flaskreact\models.py
 
#C:\flask_dev\flaskreact\models.py
from flask_sqlalchemy import SQLAlchemy
     
db = SQLAlchemy()
     
class Countries(db.Model):
    __tablename__ = "countries"
    ID = db.Column(db.Integer, primary_key=True)
    countryName = db.Column(db.String(120), index=True, unique=True)

class State(db.Model):
    __tablename__ = "state"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120), index=True, unique=True)
    country_id = db.Column(db.Integer)

class City(db.Model):
    __tablename__ = "city"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120), index=True, unique=True)
    stateid = db.Column(db.Integer)
run (venv) C:\flask_dev\flaskreact>flask run
http://127.0.0.1:5000/users/1/4

Country State and City : https://github.com/cairocodes/cairocoders/blob/main/country-state-city.sql

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

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

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

https://github.com/axios/axios

Installing the Axios Client
$ npm install axios

C:\reactdev\myreactdev>npm install axios
C:\react-js\myreactdev\src\App.js
//C:\react-js\myreactdev\src\App.js
import React, { useState, useEffect } from "react";
import "./App.css";
import axios from "axios";

function App() {
  
  const [country, setCountry]= useState([]);
  const [countryid, setCountryid]= useState('0');
  const [stateid, setStateid]= useState('0');
  const [state, setState]= useState([]);
  const [city, setCity]= useState([]);

 
  useEffect(() => {
	  
    const fetchCountry = async () => {
        axios.get('http://127.0.0.1:5000/listall')
        .then(function (response) {
            //handle success
            //console.log(response)
            setCountry(response.data)
        })
        .catch(function (response) {
            //handle error
            console.log(response)
        });
    }
  
    fetchCountry()
  }, [])
 
  const handlecountry=(event)=>{
    const getcoutryid= event.target.value;
	alert(getcoutryid);
    setCountryid(getcoutryid);
    event.preventDefault();
  }  
  
  const handlestate=(event)=>{
    const stateid= event.target.value;
	alert(stateid);
    setStateid(stateid);
    event.preventDefault();
  }
 
  useEffect( ()=>{
 
    const getstate= async ()=>{	
        axios.get(`http://127.0.0.1:5000/state/${countryid }`)
        .then(function (response) {
            //handle success
            //console.log(response)
            setState(response.data)
        })
        .catch(function (response) {
            //handle error
            console.log(response)
        });
    }
    getstate();
 
  },[countryid]);
 
  useEffect( ()=>{
 
    const getcity= async ()=>{
        axios.get(`http://127.0.0.1:5000/city/${stateid }`)
        .then(function (response) {
            //handle success
            //console.log(response)
            setCity(response.data)
        })
        .catch(function (response) {
            //handle error
            console.log(response)
        });
    }
    getcity();
 
  },[stateid]);
	
  return (
    <div className="container">
     <div className="row">
       <div className="col-sm-12">
         <h5 className="mt-4 mb-4 fw-bold">ReactJs Python Flask Dynamic Select Country State City | Axios Mysql</h5>

             <div className="row mb-3">
                 <div className="form-group col-md-12">
                 <label className="mb-2">Country</label>
                 <select name="country" className="form-select" onChange={(e)=>handlecountry(e)}>
                   <option>--Select Country--</option>
                   {
                     country.map( (getcon)=>(
                   <option key={getcon.ID} value={getcon.ID }> { getcon.countryName}</option>
                     ))
                }
                  
                 </select>
               </div>
               <div className="form-group col-md-12">
               <label className="mb-2">State</label>
               <select name="state" className="form-select" onChange={(e)=>handlestate(e)}>
                   <option>--Select State--</option>
                   {
                     state.map( (st,index)=>(                    
                   <option key={index} value={st.id}>{ st.name}</option>
                     ))
                     }
                 </select>
               </div>
 
               <div className="form-group col-md-12">
               <label className="mb-2">City</label>
               <select name="city" className="form-select">
                   <option>--Select City--</option>                  
                   {
                     city.map( (st,index)=>(                    
                   <option key={index} value={st.id}>{ st.name}</option>
                     ))
                     }
                 </select>
               </div>
			   
               <div className="form-group col-md-12 mt-12">              
               <button type="submit" className="btn btn-success mt-2" >Submit</button>               
               </div>
            </div>
            
       </div>
     </div>
    </div>
  );
}
export default App;
react-js\myreactdev\public\index.html
//react-js\myreactdev\public\index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
Run C:\react-j\myreactdev>npm start
http://localhost:3000/

ReactJs Python Flask Dynamic Select Country State Dropdown Select Box

ReactJs Python Flask Dynamic Select Country State Dropdown Select Box

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

Flask-Cors
A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.
https://pypi.org/project/Flask-Cors/

(venv) PS C:\flask_dev\flaskreact>pip install -U flask-cors

C:\flask_dev\flaskreact\app.py
 
#C:\flask_dev\flaskreact\app.py
from flask import Flask, jsonify
from flask_cors import CORS #ModuleNotFoundError: No module named 'flask_cors' = pip install Flask-Cors
from flask_marshmallow import Marshmallow #ModuleNotFoundError: No module named 'flask_marshmallow' = pip install flask-marshmallow https://pypi.org/project/flask-marshmallow/
  
from models import db, Countries, State
  
app = Flask(__name__)
CORS(app, supports_credentials=True)
  
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskdb.db'
# Databse configuration mysql                             Username:password@hostname/databasename
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:''@localhost/flaskreact'
  
db.init_app(app)
    
with app.app_context():
    db.create_all()
  
ma=Marshmallow(app)
   
class CountriesSchema(ma.Schema):
    class Meta:
        fields = ('ID','countryName')

class StateSchema(ma.Schema):
    class Meta:
        fields = ('id','name','country_id')

countries_schema = CountriesSchema(many=True)
state_schema = StateSchema(many=True)

@app.route("/")
def hello_world():
    return "Hello, World!"
  
@app.route('/listall',methods =['GET'])
def listall():
    all_countries = Countries.query.all()
    results = countries_schema.dump(all_countries)
    return jsonify(results)

@app.route('/state/<get_state>')
def statebycountry(get_state):
    state = State.query.filter_by(country_id=get_state).all()
    results = state_schema.dump(state)
    return jsonify(results)
C:\flask_dev\flaskreact\models.py
 
#C:\flask_dev\flaskreact\models.py
from flask_sqlalchemy import SQLAlchemy
     
db = SQLAlchemy()
     
class Countries(db.Model):
    __tablename__ = "countries"
    ID = db.Column(db.Integer, primary_key=True)
    countryName = db.Column(db.String(120), index=True, unique=True)

class State(db.Model):
    __tablename__ = "state"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120), index=True, unique=True)
    country_id = db.Column(db.Integer)
run (venv) C:\flask_dev\flaskreact>flask run
http://127.0.0.1:5000/users/1/4

Country and State : https://github.com/cairocodes/cairocoders/blob/main/country_state.sql

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, { useState, useEffect } from "react";
import "./App.css";

function App() {
  const [country, setCountry]= useState([]);
  const [countryid, setCountryid]= useState('0');
  const [state, setState]= useState([]);
 
  useEffect( ()=>{
   const getcountry= async ()=>{
     const req= await fetch("http://127.0.0.1:5000/listall");
     const getres= await req.json();
     console.log(getres);
     setCountry(await getres);
 
   }
   getcountry();
 
 
  },[]);
 
  const handlecountry=(event)=>{
    const getcoutryid= event.target.value;
	alert(getcoutryid);
    setCountryid(getcoutryid);
    event.preventDefault();
  }
 
  useEffect( ()=>{
 
    const getstate= async ()=>{
      const resstate= await fetch(`http://127.0.0.1:5000/state/${countryid }`);
      const getst= resstate.json();
      console.log(getst);
      setState(await getst);
 
    }
    getstate();
 
  },[countryid]);
 
    
  return (
    <div className="container">
     <div className="row">
       <div className="col-sm-12">
         <h5 className="mt-4 mb-4 fw-bold">ReactJs Python Flask Dynamic Select Country State Dropdown Select Box</h5>
            
             <div className="row mb-3">
                 <div className="form-group col-md-4">
                 <label className="mb-2">Country</label>
                 <select name="country" className="form-select" onChange={(e)=>handlecountry(e)}>
                   <option>--Select Country--</option>
                   {
                     country.map( (getcon)=>(
                   <option key={getcon.ID} value={getcon.ID }> { getcon.countryName}</option>
                     ))
                }
                  
                 </select>
               </div>
               <div className="form-group col-md-4">
               <label className="mb-2">State</label>
               <select name="state" className="form-select">
                   <option>--Select State--</option>
                   {
                     state.map( (st,index)=>(                    
                   <option key={index} value={st.id}>{ st.name}</option>
                     ))
                     }
                 </select>
               </div>
 
               <div className="form-group col-md-2 mt-4">              
               <button className="btn btn-success mt-2" >Submit</button>               
               </div>
            </div>
                
       </div>
     </div>
    </div>
  );
}
export default App;
react-js\myreactdev\public\index.html
//react-js\myreactdev\public\index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
Run C:\react-j\myreactdev>npm start
http://localhost:3000/

Related Post