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