Adding source code files for Chapter 10
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
#api_app: REST API for student resource
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask import Flask
|
||||
from flask_restful import Resource, Api, reqparse
|
||||
|
||||
app = Flask(__name__)
|
||||
api = Api(app)
|
||||
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///student.db'
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('name', type=str)
|
||||
parser.add_argument('grade', type=str)
|
||||
|
||||
class Student(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(80), nullable=False)
|
||||
grade = db.Column(db.String(20), nullable=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"{'id':{self.id}, 'name':{self.name},'grade':{self.grade}}"
|
||||
|
||||
def serialize(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'name': self.name,
|
||||
'grade': self.grade
|
||||
}
|
||||
|
||||
class StudentDao(Resource):
|
||||
def get(self, student_id):
|
||||
student = Student.query.filter_by(id=student_id).\
|
||||
first_or_404(description='Record with id={} is not available'.format(student_id))
|
||||
return student.serialize()
|
||||
|
||||
def delete(self, student_id):
|
||||
student = Student.query.filter_by(id=student_id).\
|
||||
first_or_404(description='Record with id={} is not available'.format(student_id))
|
||||
db.session.delete(student)
|
||||
db.session.commit()
|
||||
return '', 204
|
||||
|
||||
def put(self, student_id):
|
||||
student = Student.query.filter_by(id=student_id).first_or_404\
|
||||
(description='Record with id={} is not available'.format(student_id))
|
||||
args = parser.parse_args()
|
||||
name = args['name']
|
||||
grade = args['grade']
|
||||
if (name):
|
||||
student.name = name
|
||||
if (grade):
|
||||
student.grade = grade
|
||||
db.session.commit()
|
||||
return student.serialize(), 200
|
||||
|
||||
class StudentListDao(Resource):
|
||||
def get(self):
|
||||
students = Student.query.all()
|
||||
return [Student.serialize(student) for student in students]
|
||||
|
||||
def post(self):
|
||||
args = parser.parse_args()
|
||||
name = args['name']
|
||||
grade = args['grade']
|
||||
student = Student(name=name, grade=grade)
|
||||
db.session.add(student)
|
||||
db.session.commit()
|
||||
return student.serialize(), 200
|
||||
|
||||
api.add_resource(StudentDao, '/students/<student_id>')
|
||||
api.add_resource(StudentListDao, '/students')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
#app.run(debug=True)
|
||||
app.run(debug=True, host='0.0.0.0', port=8080)
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
<script src="{{ url_for('static', filename='js/test.js') }}"></script>
|
||||
<title> {% block title %} {% endblock title %} - Students</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/">Students</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
|
||||
aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="#">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">About</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{% block body %}
|
||||
|
||||
{% endblock body %}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,77 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %} Home{% endblock title %}
|
||||
{% block body %}
|
||||
|
||||
|
||||
<div class="container my-3">
|
||||
<h2>Add a Student</h2>
|
||||
<form action="/" method="POST">
|
||||
|
||||
<div class="mb-2">
|
||||
<label for="fname" class="form-label">First name</label>
|
||||
<input type="text" class="form-control" name="fname" id="fname" aria-describedby="emailHelp">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label for="lname" class="form-label">Last Name</label>
|
||||
<input type="text" class="form-control" name="lname" id="lname" aria-describedby="emailHelp">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label for="grade" class="form-label">Grade</label>
|
||||
<input type="text" class="form-control" name="grade" id="grade">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-dark">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="container my-3">
|
||||
<h2>Students</h2>
|
||||
{% if students|length == 0 %}
|
||||
<div class="alert alert-dark" role="alert">
|
||||
No student found. Add your first student now!
|
||||
</div>
|
||||
{% else %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">No</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Grade</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for student in students %}
|
||||
<tr>
|
||||
<th scope="row">{{loop.index}}</th>
|
||||
<td>{{student.name}}</td>
|
||||
<td>{{student.grade}}</td>
|
||||
<td>
|
||||
<a href="/update/{{student.id}}" type="button" class="btn btn-outline-dark btn-sm mx-1">Update</button>
|
||||
<a href="/delete/{{student.id}}" type="button" class="btn btn-outline-dark btn-sm mx-1">Delete</button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
<!-- Optional JavaScript; choose one of the two! -->
|
||||
|
||||
<!-- Option 1: Bootstrap Bundle with Popper -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0"
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<!-- Option 2: Separate Popper and Bootstrap JS -->
|
||||
<!--
|
||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.6.0/dist/umd/popper.min.js" integrity="sha384-KsvD1yqQ1/1+IA7gi3P0tyJcT3vR+NdBTt13hSJ2lnve8agRGXTTyNaBYmCR/Nwi" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.min.js" integrity="sha384-nsg8ua9HAw1y0W1btsyWgBklPnCUAFLuTMS2G72MMONqmOymq585AcH49TLBQObG" crossorigin="anonymous"></script>
|
||||
-->
|
||||
|
||||
{% endblock body %}
|
||||
@@ -0,0 +1,38 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %} Home{% endblock title %}
|
||||
{% block body %}
|
||||
|
||||
<div class="container my-3">
|
||||
<h2>Update Student</h2>
|
||||
<form action="/update/{{student.id}}" method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="fname" class="form-label">First name</label>
|
||||
<input type="text" class="form-control" name="fname" id="fname" value="{{fname}}" aria-describedby="emailHelp">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="lname" class="form-label">Last Name</label>
|
||||
<input type="text" class="form-control" name="lname" id="lname" value="{{lname}}" aria-describedby="emailHelp">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="grade" class="form-label">Grade</label>
|
||||
<input type="text" class="form-control" name="grade" id="grade" value="{{student.grade}}" >
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-dark">Update</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Optional JavaScript; choose one of the two! -->
|
||||
|
||||
<!-- Option 1: Bootstrap Bundle with Popper -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0"
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<!-- Option 2: Separate Popper and Bootstrap JS -->
|
||||
<!--
|
||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.6.0/dist/umd/popper.min.js" integrity="sha384-KsvD1yqQ1/1+IA7gi3P0tyJcT3vR+NdBTt13hSJ2lnve8agRGXTTyNaBYmCR/Nwi" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.min.js" integrity="sha384-nsg8ua9HAw1y0W1btsyWgBklPnCUAFLuTMS2G72MMONqmOymq585AcH49TLBQObG" crossorigin="anonymous"></script>
|
||||
-->
|
||||
|
||||
{% endblock body %}
|
||||
@@ -0,0 +1,46 @@
|
||||
#webapp.py: interacting with business latyer via REST API
|
||||
# for create, delete and list objects
|
||||
from flask import Flask, render_template, redirect, request
|
||||
import requests, json
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.get('/')
|
||||
def list():
|
||||
response = requests.get('http://localhost:8080/students')
|
||||
data = json.loads(response.text)
|
||||
return render_template('main.html', students=data)
|
||||
|
||||
@app.post('/')
|
||||
def add():
|
||||
fname = request.form['fname']
|
||||
lname = request.form['lname']
|
||||
grade = request.form['grade']
|
||||
payload = {'name': f"{fname} {lname}", 'grade': grade}
|
||||
respone = requests.post('http://localhost:8080/students', data=payload)
|
||||
return redirect("/")
|
||||
|
||||
@app.get('/delete/<int:id>')
|
||||
def delete(id):
|
||||
response = requests.delete('http://localhost:8080/students/'+str(id))
|
||||
return redirect("/")
|
||||
|
||||
@app.post('/update/<int:id>')
|
||||
def update(id):
|
||||
fname = request.form['fname']
|
||||
lname = request.form['lname']
|
||||
grade = request.form['grade']
|
||||
payload = {'name' : f"{fname} {lname}", 'grade':grade}
|
||||
respone = requests.put('http://localhost:8080/students/' + str(id), data = payload)
|
||||
return redirect("/")
|
||||
|
||||
@app.get('/update/<int:id>')
|
||||
def load_student_for_update(id):
|
||||
response = requests.get('http://localhost:8080/students/'+str(id))
|
||||
student = json.loads(response.text)
|
||||
fname = student['name'].split()[0]
|
||||
lname = student['name'].split()[1]
|
||||
return render_template('update.html', fname=fname, lname=lname, student= student)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, host='0.0.0.0', port=80)
|
||||
@@ -0,0 +1,80 @@
|
||||
#api_app: REST API for student resource
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask import Flask
|
||||
from flask_restful import Resource, Api, reqparse
|
||||
|
||||
app = Flask(__name__)
|
||||
api = Api(app)
|
||||
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///student.db'
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('name', type=str)
|
||||
parser.add_argument('grade', type=str)
|
||||
|
||||
class Student(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(80), nullable=False)
|
||||
grade = db.Column(db.String(20), nullable=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"{'id':{self.id}, 'name':{self.name},'grade':{self.grade}}"
|
||||
|
||||
def serialize(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'name': self.name,
|
||||
'grade': self.grade
|
||||
}
|
||||
|
||||
class StudentDao(Resource):
|
||||
def get(self, student_id):
|
||||
student = Student.query.filter_by(id=student_id).\
|
||||
first_or_404(description='Record with id={} is not available'.format(student_id))
|
||||
return student.serialize()
|
||||
|
||||
def delete(self, student_id):
|
||||
student = Student.query.filter_by(id=student_id).\
|
||||
first_or_404(description='Record with id={} is not available'.format(student_id))
|
||||
db.session.delete(student)
|
||||
db.session.commit()
|
||||
return '', 204
|
||||
|
||||
def put(self, student_id):
|
||||
student = Student.query.filter_by(id=student_id).first_or_404\
|
||||
(description='Record with id={} is not available'.format(student_id))
|
||||
args = parser.parse_args()
|
||||
name = args['name']
|
||||
grade = args['grade']
|
||||
if (name):
|
||||
student.name = name
|
||||
if (grade):
|
||||
student.grade = grade
|
||||
db.session.commit()
|
||||
return student.serialize(), 200
|
||||
|
||||
class StudentListDao(Resource):
|
||||
def get(self):
|
||||
students = Student.query.all()
|
||||
return [Student.serialize(student) for student in students]
|
||||
|
||||
def post(self):
|
||||
args = parser.parse_args()
|
||||
name = args['name']
|
||||
grade = args['grade']
|
||||
student = Student(name=name, grade=grade)
|
||||
db.session.add(student)
|
||||
db.session.commit()
|
||||
return student.serialize(), 200
|
||||
|
||||
api.add_resource(StudentDao, '/students/<student_id>')
|
||||
api.add_resource(StudentListDao, '/students')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
#app.run(debug=True)
|
||||
app.run(debug=True, host='0.0.0.0', port=8080)
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#app1.py: routing in a Flask application
|
||||
from flask import Flask
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/')
|
||||
def hello():
|
||||
return 'Hello World!'
|
||||
|
||||
@app.route('/greeting')
|
||||
def greeting():
|
||||
return 'Greetings from Flask web app!'
|
||||
|
||||
@app.route('/hello/<name>')
|
||||
def hello_user(name):
|
||||
return f'Hello {name}!'
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@@ -0,0 +1,22 @@
|
||||
#app2.py: map request with method type
|
||||
from flask import Flask, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/submit', methods=['GET'])
|
||||
def req_with_get():
|
||||
return "Received a get request"
|
||||
|
||||
@app.post('/submit')
|
||||
def req_with_post():
|
||||
return "Received a post request"
|
||||
|
||||
@app.route('/submit2', methods = ['GET', 'POST'])
|
||||
def both_get_post():
|
||||
if request.method == 'POST':
|
||||
return "Received a post request 2"
|
||||
else:
|
||||
return "Received a get request 2"
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@@ -0,0 +1,17 @@
|
||||
#app3.py: rendering static and dynamic contents
|
||||
from flask import Flask, render_template, url_for, redirect
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/hello')
|
||||
def hello():
|
||||
hello_url = url_for ('static', filename='app3.html')
|
||||
return redirect(hello_url)
|
||||
|
||||
@app.route('/greeting')
|
||||
def greeting():
|
||||
msg = "Hello from Python"
|
||||
return render_template('app3.html', greeting=msg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@@ -0,0 +1,25 @@
|
||||
#app4.py: extracting parameters from different requests
|
||||
from flask import Flask, request, render_template
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/hello')
|
||||
@app.route('/hello/<fname> <lname>')
|
||||
def hello_user(fname=None, lname=None):
|
||||
return render_template('app4.html', name=f"{fname} {lname}")
|
||||
|
||||
@app.get('/submit')
|
||||
def process_get_request_data():
|
||||
fname = request.args['fname']
|
||||
lname = request.args.get('lname', '')
|
||||
return render_template('app4.html', name=f"{fname} {lname}")
|
||||
|
||||
@app.post('/submit')
|
||||
def process_post_request_data():
|
||||
fname = request.form['fname']
|
||||
lname = request.form.get('lname','')
|
||||
#lname = request.form['lname']
|
||||
return render_template('app4.html', name=f"{fname} {lname}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@@ -0,0 +1,56 @@
|
||||
#app5.py: interacting with db for create, delete and list objects
|
||||
from flask import Flask, request, render_template, redirect
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from werkzeug.exceptions import HTTPException
|
||||
import json
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///student.db'
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
class Student(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(80), nullable=False)
|
||||
grade = db.Column(db.String(20), nullable=True)
|
||||
|
||||
def __repr__(self):
|
||||
return '<Student %r>' % self.name
|
||||
|
||||
@app.get('/list')
|
||||
def list_students():
|
||||
student_list = Student.query.all()
|
||||
return render_template('app5.html', students=student_list)
|
||||
|
||||
|
||||
@app.get('/add')
|
||||
def add_student():
|
||||
fname = request.args['fname']
|
||||
lname = request.args.get('lname', '')
|
||||
grade = request.args.get('grade','')
|
||||
student = Student(name=f"{fname} {lname}", grade=grade)
|
||||
db.session.add(student)
|
||||
db.session.commit()
|
||||
return redirect("/list")
|
||||
|
||||
@app.get('/delete/<int:id>')
|
||||
def del_student(id):
|
||||
todelete = Student.query.filter_by(id=id).first()
|
||||
db.session.delete(todelete)
|
||||
db.session.commit()
|
||||
return redirect("/list")
|
||||
|
||||
@app.errorhandler(HTTPException)
|
||||
def page_not_found(error):
|
||||
print(error)
|
||||
response = error.get_response()
|
||||
# replace the body with JSON
|
||||
response.data = json.dumps({
|
||||
"code": error.code,
|
||||
"name": error.name,
|
||||
"description": error.description,
|
||||
})
|
||||
return response
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@@ -0,0 +1,36 @@
|
||||
#app6.py: error and exception handling
|
||||
import json
|
||||
from flask import Flask, render_template, abort
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.get('/')
|
||||
def hello():
|
||||
return 'Hello World!'
|
||||
|
||||
@app.route('/greeting')
|
||||
def greeting():
|
||||
x = 10/0
|
||||
return 'Greetings from Flask web app!'
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(error):
|
||||
return render_template('error404.html'), 404
|
||||
|
||||
@app.errorhandler(500)
|
||||
def internal_error(error):
|
||||
return render_template('error500.html'), 500
|
||||
|
||||
@app.errorhandler(HTTPException)
|
||||
def generic_handler(error):
|
||||
|
||||
error_detail = json.dumps({
|
||||
"code": error.code,
|
||||
"name": error.name,
|
||||
"description": error.description,
|
||||
})
|
||||
return render_template('error.html', err_msg=error_detail), error.code
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1> Hello World from a static file </h1>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Dynamic contents demo</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% if greeting %}
|
||||
<h1> {{ greeting }}!</h1>
|
||||
{% endif %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Dynamic contents demo</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% if name %}
|
||||
<h1>Hello {{ name }}!</h1>
|
||||
{% else %}
|
||||
<h1>Hello, whoever you are!</h1>
|
||||
{% endif %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Students from database</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Students</h2>
|
||||
{% if students|length > 0 %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">SNo</th>
|
||||
<th scope="col">name</th>
|
||||
<th scope="col">grade</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for student in students %}
|
||||
<tr>
|
||||
<td scope="row">{{student.id}}</td>
|
||||
<td>{{student.name}}</td>
|
||||
<td>{{student.grade}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Error page</title>
|
||||
</head>
|
||||
<body>
|
||||
<h3>{{ err_msg }}</h3>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Error page</title>
|
||||
</head>
|
||||
<body>
|
||||
<h3>The page you request does not exist. Please check your URL.</h3>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Error page</title>
|
||||
</head>
|
||||
<body>
|
||||
<h3>There is an internal server problem. Please try again later.</h3>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user