article

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

Thursday, April 18, 2024

Next.js 14 Python Flask Dynamic Select Country State City Mysql | TailwindCSS DaisyUI

Next.js 14 Python Flask Dynamic Select Country State City Mysql | TailwindCSS DaisyUI

https://python-guide-es.readthedocs.io/es/guide-es/dev/virtualenvs.html

Create an environment
ednalan@Cairocoders myapp % pip install virtualenv
ednalan@Cairocoders myapp % pip install virtualenv

Activate the environment
ednalan@Cairocoders myapp % source venv/bin/activate
(venv) ednalan@Cairocoders myapp %

Install Flask
https://pypi.org/project/Flask/
(venv) ednalan@Cairocoders myapp % pip install -U Flask
(venv) ednalan@Cairocoders myapp % flask run

Install requirements
pip install -U flask-cors
https://pypi.org/project/Flask-Cors/

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

python3 -m pip install
https://pypi.org/project/pymysql/
app.py
//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:root@localhost:8889/nextjsdb'
   
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>',methods =['GET'])
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>',methods =['GET'])
def city(get_city):
    city_data = City.query.filter_by(stateid=get_city).all()
    results = city_schema.dump(city_data)
    return jsonify(results)

if __name__ == "__main__":
    app.run(debug=True)
models.py
//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)
Country State and City : https://github.com/cairocodes/cairocoders/blob/main/country-state-city.sql

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

Next.js
Install requirements
npm install axios
https://www.npmjs.com/package/axios

app\page.tsx
//app\page.tsx
import Form from "@/components/form";

export default function Home() {
  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center">
      <div className="flex items-center justify-between gap-1 mb-5">
        <h1 className="text-4xl font-bold">Next.js 14 Python Flask Dynamic Select Country State City Mysql | TailwindCSS DaisyUI</h1>
      </div>    
      <div className="overflow-x-auto">
          <Form/>
      </div>  
    </div>
  );
}
components\form.tsx
//components\form.tsx
"use client";
 
import React, { useEffect, useState } from "react";
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios

export default function Form() {

    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;
        console.log(getcoutryid);
        setCountryid(getcoutryid);
        event.preventDefault();
    }  
    
    const handlestate=(event)=>{
        const stateid= event.target.value;
        console.log(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="max-w-xl mx-auto mt-5">
            <div>
            <form>
            <div className="mb-5 pr-4 pl-4">
                <label className="block text-sm font-medium text-gray-900">
                    Country
                </label>
                <select onChange={(e)=>handlecountry(e)} name="country" className="select select-info w-full max-w-xs">
                    <option defaultValue={'DEFAULT'}>--Select Country--</option>
                    {
                     country.map( (getcon)=>(
                        <option key={getcon.ID} value={getcon.ID }> { getcon.countryName}</option>
                     ))
                    }
                </select>
            </div>
            <div className="mb-5 pr-4 pl-4">
                <label className="block text-sm font-medium text-gray-900">
                    State
                </label>
                <select onChange={(e)=>handlestate(e)} name="state" className="select select-success w-full max-w-xs">
                   <option defaultValue={'DEFAULT'}>--Select State--</option>
                   {
                     state.map( (st,index)=>(                    
                        <option key={index} value={st.id}>{ st.name}</option>
                     ))
                     }
                 </select>
            </div>
            <div className="mb-5 pr-4 pl-4">
                <label className="block text-sm font-medium text-gray-900">
                    City
                </label>
                <select name="city" className="select select-warning w-full max-w-xs">
                   <option>--Select City--</option>                  
                    {
                     city.map( (st,index)=>(                    
                        <option key={index} value={st.id}>{ st.name}</option>
                     ))
                    }
                 </select>
            </div>
        </form>
        </div>
        </div>
        
        </>
  );
}
run C:\nextjs>npm run dev

Thursday, April 11, 2024

Next.js 14 Python Flask Mysql Pagination Next Prev | TailwindCSS DaisyUI

Next.js 14 Python Flask Mysql Pagination Next Prev | TailwindCSS DaisyUI

https://python-guide-es.readthedocs.io/es/guide-es/dev/virtualenvs.html

Create an environment
ednalan@Cairocoders myapp % pip install virtualenv
ednalan@Cairocoders myapp % pip install virtualenv

Activate the environment
ednalan@Cairocoders myapp % source venv/bin/activate
(venv) ednalan@Cairocoders myapp %

Install Flask
https://pypi.org/project/Flask/
(venv) ednalan@Cairocoders myapp % pip install -U Flask
(venv) ednalan@Cairocoders myapp % flask run

Install requirements
pip install -U flask-cors
https://pypi.org/project/Flask-Cors/

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

python3 -m pip install
https://pypi.org/project/pymysql/
app.py
//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:root@localhost:8889/nextjsdb'
   
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=3):
    
    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,
            'price': rs.price
        } for rs in products.items]
    })
   
if __name__ == "__main__":
    app.run(debug=True)
models.py
//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)
    image = db.Column(db.String(150), index=True)
    price = db.Column(db.Integer,default=0)
run (venv) C:\flask_dev\myapp>flask run

Next.js
Install requirements
npm install axios
https://www.npmjs.com/package/axios

app\page.tsx
//app\page.tsx
import Link from "next/link";
import TableData from "@/components/tabledata";
import { Suspense } from "react";
import { Spinner } from "@/components/spinner";
 
export default function Home() {
  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center bg-gray-300">
      <div className="flex items-center justify-between gap-1 mb-5">
        <h1 className="text-4xl font-bold">Next.js 14 Python Flask Mysql Pagination Next Prev | TailwindCSS DaisyUI</h1>
      </div>    
      <Suspense fallback={<Spinner />}>
        <TableData/>
      </Suspense>
    </div>
  );
}
components\tabledata.tsx
//components\tabledata.tsx
"use client";

import React, { useEffect, useState } from "react";
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios
import Image from 'next/image' 

export default function Users() {
    const [products, setProducts] = useState([]);
    const [info, setInfo] = useState({});

    const url = "http://127.0.0.1:5000/products/1/3";

    useEffect(() => {
        fetchProducts(url);
    }, []);

    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);
    };

    return (
            <div className="py-16">
            <div className="container mx-auto px-4">
                <h2 className="text-3xl font-bold text-white mb-8">Introducing Our Latest Product</h2>
                <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
                
                {products.map((item, index) => (
                <div key={index} className="bg-white rounded-lg shadow-lg p-8">
                    <div className="relative overflow-hidden">
                        <Image
                        src={`http://127.0.0.1:5000/static/images/${item.image}`}
                        width={400}
                        height={400}
                        alt="Photo"
                        />
                    <div className="absolute inset-0 bg-black opacity-40" />
                    <div className="absolute inset-0 flex items-center justify-center">
                        <button className="bg-white text-gray-900 py-2 px-6 rounded-full font-bold hover:bg-gray-300">View Product</button>
                    </div>
                    </div>
                    <h3 className="text-xl font-bold text-gray-900 mt-4">{item.name}</h3>
                    <p className="text-gray-500 text-sm mt-2">Description: {item.name}</p>
                    <div className="flex items-center justify-between mt-4">
                    <span className="text-gray-900 font-bold text-lg">${item.price}.99</span>
                    <button className="bg-gray-900 text-white py-2 px-4 rounded-full font-bold hover:bg-gray-800">Add to Cart</button>
                    </div>
                </div>
                ))}

                </div>
                <div className="w-1/2 items-center px-4 mt-6">   
                    <div className="join grid grid-cols-2">
                        {info.prev_page_url ? (
                            <button className="join-item btn btn-primary btn-outline" onClick={handlePreviousPage}>
                            Previous
                            </button>
                        ) : null}
                        {info.next_page_url ? (
                            <button className="join-item btn btn-primary btn-outline" onClick={handleNextPage}>
                            Next
                            </button>
                        ) : null}
                    </div>
                </div> 
            </div>
            </div>
  );
}
components\spinner.tsx
//components\spinner.tsx
export const Spinner = () => {
  return (
    <span className="loading loading-spinner loading-lg"></span>
  );
};
run C:\nextjs>npm run dev
https://github.com/cairocodes/Next.js-14-Python-Flask-Mysql-Pagination-Next-Prev-TailwindCSS-DaisyUI

Thursday, April 4, 2024

Next.js 14 Python Flask CRUD Mysql (Create Read Update and Delete)| TailwindCSS DaisyUI

Next.js 14 Python Flask CRUD Mysql (Create Read Update and Delete)| TailwindCSS DaisyUI

https://python-guide-es.readthedocs.io/es/guide-es/dev/virtualenvs.html

Create an environment
ednalan@Cairocoders myapp % pip install virtualenv
ednalan@Cairocoders myapp % pip install virtualenv

Activate the environment
ednalan@Cairocoders myapp % source venv/bin/activate
(venv) ednalan@Cairocoders myapp %

Install Flask
https://pypi.org/project/Flask/
(venv) ednalan@Cairocoders myapp % pip install -U Flask
(venv) ednalan@Cairocoders myapp % flask run

Install requirements
pip install -U flask-cors
https://pypi.org/project/Flask-Cors/

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 + marshmallow for beautiful APIs
https://pypi.org/project/flask-marshmallow/

(venv) PS C:\flask_dev\myapp>pip install flask-marshmallow

python3 -m pip install
https://pypi.org/project/pymysql/
app.py
 
//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:root@localhost:8889/flasknextjs' #python3 -m pip install PyMySQL https://pypi.org/project/pymysql/
                                                        
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)
models.py
 
//models.py
from flask_sqlalchemy import SQLAlchemy #pip install -U Flask-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)
    email = db.Column(db.String(150), index=True, unique=True)
    password = db.Column(db.String(255), index=True)
run (venv) C:\flask_dev\myapp>flask run

Next.js Install requirements
npm install axios
https://www.npmjs.com/package/axios

app\page.tsx
//app\page.tsx
import Link from "next/link";
import TableData from "@/components/tabledata";
import { Suspense } from "react";
import { Spinner } from "@/components/spinner";
 
export default function Home() {
    return (
    <div className="w-screen py-20 flex justify-center flex-col items-center">
      <div className="flex items-center justify-between gap-1 mb-5">
        <h1 className="text-4xl font-bold">Next.js 14 Python Flask CRUD Mysql (Create Read Update and Delete)| TailwindCSS DaisyUI</h1>
      </div>    
        <div className="overflow-x-auto">
          <div className="mb-2 w-full text-right">
            <Link
              href="/user/create"
              className="btn btn-primary">
              Create
            </Link>
          </div>
          <Suspense fallback={<Spinner />}>
            <TableData/>
          </Suspense>
      </div>  
    </div>
  ); 
}
components\tabledata.tsx
//components\tabledata.tsx
"use client";
  
import React, { useEffect, useState } from "react";
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios
import Link from "next/link";

export default function Users() {
    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 (
        <table className="table table-zebra">
        <thead className="text-sm text-gray-700 uppercase bg-gray-50">
            <tr>
            <th className="py-3 px-6">#</th>
            <th className="py-3 px-6">Name</th>
            <th className="py-3 px-6">Email</th>
            <th className="py-3 px-6">Password</th>
            <th className="py-3 px-6 text-center">Actions</th>
            </tr>
        </thead>
        <tbody>
            {userData.map((rs, index) => (
            <tr key={rs.id} className="bg-white border-b">
                <td className="py-3 px-6">{index + 1}</td>
                <td className="py-3 px-6">{rs.name}</td>
                <td className="py-3 px-6">{rs.email}</td>
                <td className="py-3 px-6">{rs.password}</td>
                <td className="flex justify-center gap-1 py-3">
                    <Link
                    href={`/user/view/${rs.id}`} 
                    className="btn btn-info">
                    View
                    </Link>
                    <Link
                    href={`/user/edit/${rs.id}`} 
                    className="btn btn-primary">
                    Edit
                    </Link>
                    <button onClick={()=>handleDelete(rs.id)} className="btn btn-secondary">Delete</button>
                </td>
            </tr>
            ))}
        </tbody>
        </table>
  );
}
components\spinner.tsx
//components\spinner.tsx
export const Spinner = () => {
  return (
    <span className="loading loading-spinner loading-lg"></span>
  );
};
app\user\create\page.tsx
//app\user\create\page.tsx
"use client";

import React, { useState } from "react";
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios

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

    const onSubmitChange = async (e) => {
        e.preventDefault();
        try {
          const responce= await axios.post("http://127.0.0.1:5000/newuser", userField);
          console.log(responce)
          window.location.href = '/';
        } catch (err) {
            console.log("Something Wrong");
        }
    }
    return (
    <div className="max-w-md mx-auto mt-5">
        <h1 className="text-2xl text-center mb-2">Add New User</h1>
        <div>
        <form>
        <div className="mb-5">
          <label htmlFor="name" className="block text-sm font-medium text-gray-900">
            Full Name
          </label>
          <input
            type="text"
            name="name"
            id="name"
            className="input input-bordered input-primary w-full max-w-xs"
            placeholder="Full Name..."
            onChange={e => changeUserFieldHandler(e)} 
          />
        </div>
        <div className="mb-5">
          <label htmlFor="email" className="block text-sm font-medium text-gray-900">
            Email
          </label>
          <input
            type="email"
            name="email"
            id="email"
            className="input input-bordered input-primary w-full max-w-xs"
            placeholder="Email..."
            onChange={e => changeUserFieldHandler(e)}
          />
        </div>
        <div className="mb-5">
          <label
            htmlFor="password" className="block text-sm font-medium text-gray-900">
            Password
          </label>
          <input
            type="text"
            name="password"
            id="password"
            className="input input-bordered input-primary w-full max-w-xs"
            placeholder="Password..."
            onChange={e => changeUserFieldHandler(e)}
          />
        </div>
         <button type="submit" className="btn btn-primary" onClick={e => onSubmitChange(e)}>Add User</button> 
      </form>
    </div>
    </div>
  );
};
  
export default CreateUserPage;
app\user\edit\[id]\page.tsx
//app\user\edit\[id]\page.tsx
"use client";

import React, { useState, useEffect } from 'react';
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios
import Link from "next/link";
import { useParams } from 'next/navigation'

export default function ViewUserPage() {
    const {id}=useParams();

    console.log(id);
 
    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);
            window.location.href = '/';
        } catch (err) {
            console.log("Something Wrong");
        }
    }

    return (
    <div className="max-w-md mx-auto mt-5">
      <h1 className="text-2xl text-center mb-2">Edit Form</h1>
            <form>
                <div className="mb-3 mt-3">
                    <label className="block text-sm font-medium text-gray-900"> ID:</label>
                    <input type="text" id="id" name="id" value={id} disabled />
                </div>
                <div className="mb-3 mt-3">
                    <label className="block text-sm font-medium text-gray-900"> Full Name:</label>
                    <input type="text" className="input input-bordered input-primary w-full max-w-xs" placeholder="Enter Your Full Name" name="name" value={userField.name} onChange={e => changeUserFieldHandler(e)} />
                </div>
                <div className="mb-3 mt-3">
                    <label className="block text-sm font-medium text-gray-900">Email:</label>
                    <input type="email" className="input input-bordered input-primary w-full max-w-xs" id="email" placeholder="Enter email" name="email" value={userField.email}  onChange={e => changeUserFieldHandler(e)}/>
                </div>
                <div className="mb-3 mt-3">
                     <label className="block text-sm font-medium text-gray-900">Password:</label>
                      <input type="text" className="input input-bordered input-primary w-full max-w-xs" 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>
  );
}
app\user\view\[id]\page.tsx
//app\user\view\[id]\page.tsx
"use client";

import React, { useState, useEffect } from 'react';
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios
import Link from "next/link";
import { useParams } from 'next/navigation'

export default function ViewUserPage() {
    const {id}=useParams();

    console.log(id);

    const[user,setUser]=useState([]);
 
    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");
        }
    }

    return (
    <div className="max-w-md mx-auto mt-5">
      <h1 className="text-2xl text-center mb-2">View User</h1>
      <table className="table table-zebra">
          <thead className="text-sm text-gray-700 uppercase bg-gray-50">
            <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>
  );
}
run C:\nextjs>npm run dev
Github - Next.js 14 Python Flask CRUD Mysql (Create Read Update and Delete)| TailwindCSS DaisyUI

Next.js 14 Python Flask Mysql List All Data | TailwindCSS DaisyUI

Next.js 14 Python Flask Mysql List All Data | TailwindCSS DaisyUI

https://python-guide-es.readthedocs.io/es/guide-es/dev/virtualenvs.html

Create an environment
ednalan@Cairocoders myapp % pip install virtualenv
ednalan@Cairocoders myapp % pip install virtualenv

Activate the environment
ednalan@Cairocoders myapp % source venv/bin/activate
(venv) ednalan@Cairocoders myapp %

Install Flask
https://pypi.org/project/Flask/
(venv) ednalan@Cairocoders myapp % pip install -U Flask
(venv) ednalan@Cairocoders myapp % flask run

Install requirements
pip install -U flask-cors
https://pypi.org/project/Flask-Cors/

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 + marshmallow for beautiful APIs
https://pypi.org/project/flask-marshmallow/

(venv) PS C:\flask_dev\myapp>pip install flask-marshmallow

python3 -m pip install
https://pypi.org/project/pymysql/
app.py
 
//app.py
from flask import Flask, jsonify, request
from flask_marshmallow import Marshmallow #ModuleNotFoundError: No module named 'flask_marshmallow' = pip install flask-marshmallow 
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:root@localhost:8889/flasknextjs' #python3 -m pip install PyMySQL https://pypi.org/project/pymysql/
                                                        
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():
    return "Hello, World!"
 
@app.route('/users', methods=['GET']) 
def listusers():
    all_users = Users.query.all()
    results = users_schema.dump(all_users)
    return jsonify(results)

if __name__ == "__main__":
    app.run(debug=True)
models.py
 
//models.py
from flask_sqlalchemy import SQLAlchemy #pip install -U Flask-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\myapp>flask run

Next.js Install requirements
npm install axios
https://www.npmjs.com/package/axios

app\page.tsx
//app\page.tsx
"use client";
  
import React, { useEffect, useState } from "react";
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios
import Link from "next/link";

export default function Home() {
    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");
        }
    }

  return (
<div className="w-screen py-20 flex justify-center flex-col items-center">
      <div className="flex items-center justify-between gap-1 mb-5">
        <h1 className="text-4xl font-bold">Next.js 14 Python Flask Mysql List All Data | TailwindCSS DaisyUI</h1>
      </div>    
      <div className="overflow-x-auto">
          <div className="mb-2 w-full text-right">
            <Link
              href="#"
              className="btn btn-primary">
              Create
            </Link>
          </div>
        <table className="table table-zebra">
        <thead className="text-sm text-gray-700 uppercase bg-gray-50">
            <tr>
            <th className="py-3 px-6">#</th>
            <th className="py-3 px-6">Name</th>
            <th className="py-3 px-6">Email</th>
            <th className="py-3 px-6">Password</th>
            <th className="py-3 px-6 text-center">Actions</th>
            </tr>
        </thead>
        <tbody>
            {userData.map((rs, index) => (
            <tr key={rs.id} className="bg-white border-b">
                <td className="py-3 px-6">{index + 1}</td>
                <td className="py-3 px-6">{rs.name}</td>
                <td className="py-3 px-6">{rs.email}</td>
                <td className="py-3 px-6">{rs.password}</td>
                <td className="flex justify-center gap-1 py-3">
                    <button className="btn btn-active btn-primary">Edit</button>
                    <button className="btn btn-active btn-secondary">Delete</button>
                </td>
            </tr>
            ))}
        </tbody>
        </table>
      </div>  
    </div>
  );
}
run C:\nextjs>npm run dev
Github - Next.js 14 Python Flask Mysql List All Data | TailwindCSS DaisyUI

Wednesday, April 3, 2024

Next.Js Python Flask

Next.Js Python Flask

https://python-guide-es.readthedocs.io/es/guide-es/dev/virtualenvs.html

Create an environment
ednalan@Cairocoders myapp % pip install virtualenv
ednalan@Cairocoders myapp % pip install virtualenv

Activate the environment
ednalan@Cairocoders myapp % source venv/bin/activate
(venv) ednalan@Cairocoders myapp %

Install Flask
https://pypi.org/project/Flask/
(venv) ednalan@Cairocoders myapp % pip install -U Flask
(venv) ednalan@Cairocoders myapp % flask run

Install requirements
pip install -U flask-cors
https://pypi.org/project/Flask-Cors/

app.py
//app.py
from flask import Flask, jsonify
from flask_cors import CORS #pip install -U flask-cors https://pypi.org/project/Flask-Cors/

# app instance
app = Flask(__name__)
CORS(app)

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

# /api/user
@app.route("/api/user", methods=['GET'])
def return_home():
    return jsonify({
        'name': ['cairocoders', 'clydey', 'caitlyn'],
        'email': ['cairocoders@gmail.com', 'clydey@gmail.com', 'caitlyn@gmail.com']
    })


if __name__ == "__main__":
    app.run(debug=True, port=8080)
Install Nextjs 14
https://nextjs.org/docs/getting-started/installation
app\page.tsx
//app\page.tsx
"use client";
  
import React, { useEffect, useState } from "react";

export default function Home() {
  const [message, setMessage] = useState("Loading");
  const [userData, setUSerData] = useState([]);
            
    fetch("http://127.0.0.1:5000/api/user")
      .then((response) => response.json())
      .then((data) => {
        console.log(data);
        setMessage(data.message);
        setUSerData(data.name)
      });
  }, []);

  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <h3>Next js Python Flask</h3>
      <div>{message}</div>
      {userData.map((user, index) => (
        <div key={index}>{user}</div>
      ))}
    </main>
  );
}
app\page.tsx axios
"use client";
  
import React, { useEffect, useState } from "react";
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios

export default function Home() {
    const [userData, setUSerData] = useState([]);
    useEffect(() => {
        fetchData();
    }, [])
 
    const fetchData = async () => {
        try {
            const result = await axios("http://127.0.0.1:5000/api/user");
            console.log(result.data);
            setUSerData(result.data.name)
        } catch (err) {
            console.log("somthing Wrong");
        }
    }

  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <h3>Next js Python Flask</h3>
      {userData.map((user, index) => (
        <div key={index}>{user}</div>
      ))}
    </main>
  );
}

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/

Related Post