├── .gitignore ├── README.md ├── lab_01_Helloworld └── main.py ├── lab_02_Blueprints ├── __init__.py ├── app │ ├── models.py │ ├── serialize.py │ └── views.py ├── config.py ├── run.py ├── templates │ └── app │ │ ├── add.html │ │ ├── edit.html │ │ ├── register.html │ │ ├── save.html │ │ └── students.html └── utils │ └── serialize.py ├── lab_02_Building_Web_Applications_with_Flask ├── models.py ├── serialize.py ├── templates │ ├── add.html │ ├── edit.html │ ├── register.html │ ├── save.html │ └── students.html └── views.py ├── lab_03_RESTful_via_Flask ├── main.py └── print_request_headers.py ├── lab_04_RESTful_Client ├── delete_requests.py ├── get_requests.py ├── post_requests.py ├── receive.html └── show_students.html ├── lab_05_Visualization_via_D3 ├── index.html └── main.py ├── lab_06_Authentication ├── auth.py └── main.py ├── lab_07_MongoDB ├── dbtest.py └── models.py └── lab_08_ORM ├── database.py ├── dbtest.py └── models.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .gitignore 3 | .idea/ 4 | lab_02_Building_Web_Applications_with_Flask/__pycache__/ 5 | lab_02_Blueprints/__pycache__/ 6 | lab_02_Blueprints/app/__pycache__/ 7 | lab_02_Blueprints/utils/__pycache__/ 8 | lab_07_orm/__pycache__/ 9 | lab_08_authentication/__pycache__/ 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # comp9321 2 | COMP9321, UNSW Sydney 3 | Data Services Engineering Lab 4 | -------------------------------------------------------------------------------- /lab_01_Helloworld/main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | 6 | @app.route("/") 7 | def hello(): 8 | return "Hello World!" 9 | 10 | 11 | if __name__ == "__main__": 12 | app.run() 13 | -------------------------------------------------------------------------------- /lab_02_Blueprints/__init__.py: -------------------------------------------------------------------------------- 1 | from lab_02_Blueprints.app.views import bp as controllers 2 | from flask import Flask 3 | app = Flask(__name__) 4 | app.register_blueprint(controllers) 5 | -------------------------------------------------------------------------------- /lab_02_Blueprints/app/models.py: -------------------------------------------------------------------------------- 1 | class Teacher: 2 | 3 | def __init__(self, name, course, students={}, username=None, password=None): 4 | super().__init__() 5 | self.password = password 6 | self.username = username 7 | self.name = name 8 | self.course = course 9 | self.students = students 10 | 11 | 12 | class Student: 13 | def __init__(self, id, first_name, last_name, gender='MALE'): 14 | super().__init__() 15 | self.id = id 16 | self.first_name = first_name 17 | self.last_name = last_name 18 | self.gender = gender 19 | -------------------------------------------------------------------------------- /lab_02_Blueprints/app/serialize.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | import pickle 3 | 4 | 5 | def serialize(object): 6 | return codecs.encode(pickle.dumps(object, pickle.HIGHEST_PROTOCOL), "base64").decode() 7 | 8 | 9 | def deserialize(object_string): 10 | return pickle.loads(codecs.decode(object_string.encode(), "base64")) 11 | -------------------------------------------------------------------------------- /lab_02_Blueprints/app/views.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from flask import Blueprint 4 | from flask import request, render_template, redirect, url_for, make_response, session, Flask 5 | 6 | from lab_02_Blueprints.app.models import Teacher, Student 7 | from lab_02_Blueprints.utils.serialize import deserialize, serialize 8 | 9 | bp = Blueprint('app', __name__, url_prefix='') 10 | 11 | 12 | @bp.route('/', methods=['GET']) 13 | def index(): 14 | teacher = retrieve_teacher() 15 | if teacher is None: 16 | return redirect(url_for(".register")) 17 | 18 | return redirect(url_for(".show_students")) 19 | 20 | 21 | @bp.route('/register', methods=["POST", "GET"]) 22 | def register(): 23 | if request.method == 'GET': 24 | return render_template("app/register.html") 25 | else: 26 | name = request.form.get("name") 27 | course = request.form.get("course") 28 | teacher = Teacher(name, course) 29 | 30 | session["_teacher"] = serialize(teacher) 31 | return redirect(url_for(".index")) 32 | 33 | 34 | @bp.route('/students', methods=["GET"]) 35 | def show_students(): 36 | teacher = retrieve_teacher() 37 | if teacher is None: 38 | return redirect("register") 39 | else: 40 | return render_template("app/students.html", students=teacher.students.values()) 41 | 42 | 43 | @bp.route('/add', methods=["POST", "GET"]) 44 | def add(): 45 | if request.method == 'GET': 46 | return render_template("app/add.html") 47 | else: 48 | id = request.form.get("id") 49 | firstname = request.form.get("firstname") 50 | lastname = request.form.get("lastname") 51 | gender = request.form.get("gender") 52 | 53 | teacher = retrieve_teacher() 54 | teacher.students[id] = Student(id, firstname, lastname, gender) 55 | session['_teacher'] = serialize(teacher) 56 | 57 | return redirect(url_for(".show_students")) 58 | 59 | 60 | @bp.route('/delete/', methods=["GET", "POST", "DELETE"]) 61 | def delete(id): 62 | teacher = retrieve_teacher() 63 | teacher.students.pop(id) 64 | session['_teacher'] = serialize(teacher) 65 | 66 | return redirect(url_for(".show_students")) 67 | 68 | 69 | @bp.route('/edit/', methods=["POST", "GET"]) 70 | def edit(id): 71 | teacher = retrieve_teacher() 72 | student = teacher.students.pop(id) 73 | 74 | if request.method == 'GET': 75 | return render_template("app/edit.html", student=student) 76 | else: 77 | student.first_name = request.form.get("firstname") 78 | student.last_name = request.form.get("lastname") 79 | student.gender = request.form.get("gender") 80 | 81 | teacher.students[id] = student 82 | session['_teacher'] = serialize(teacher) 83 | return redirect(url_for(".show_students")) 84 | 85 | 86 | @bp.route('/save') 87 | def save(): 88 | serialized_teacher = session.get("_teacher") 89 | resp = make_response(render_template("app/save.html")) 90 | if serialized_teacher is not None: 91 | expire_date = datetime.datetime.now() + datetime.timedelta(days=90) 92 | resp.set_cookie("_teacher", serialized_teacher, expires=expire_date) 93 | 94 | return resp 95 | 96 | 97 | def retrieve_teacher(): 98 | serialized_teacher = session.get("_teacher") 99 | if serialized_teacher is None: 100 | serialized_teacher = request.cookies.get('_teacher') 101 | 102 | if serialized_teacher is not None: 103 | return deserialize(serialized_teacher) 104 | 105 | return None 106 | -------------------------------------------------------------------------------- /lab_02_Blueprints/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | DEBUG = True 4 | BASE_DIR = os.path.abspath(os.path.dirname(__file__)) 5 | SECRET_KEY = "SPECIFY_YOUR_OWN_SECRET_KEY2" 6 | SESSION_TYPE = "filesystem" 7 | -------------------------------------------------------------------------------- /lab_02_Blueprints/run.py: -------------------------------------------------------------------------------- 1 | from lab_02_Blueprints import app 2 | 3 | app.config.from_object('config') 4 | app.run() 5 | -------------------------------------------------------------------------------- /lab_02_Blueprints/templates/app/add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 |
id
First name
Last name
Gender 25 | 29 |
33 |
34 | 35 | -------------------------------------------------------------------------------- /lab_02_Blueprints/templates/app/edit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 |
id{{student.id}}
First name
Last name
Gender 25 | 29 |
32 | 33 |
34 | 35 | -------------------------------------------------------------------------------- /lab_02_Blueprints/templates/app/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Register 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
Name
Course
19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /lab_02_Blueprints/templates/app/save.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Saved 6 | 7 | 8 | Return to the students page 9 | 10 | -------------------------------------------------------------------------------- /lab_02_Blueprints/templates/app/students.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Students List 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
Student List
14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% for s in students: %} 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 36 | {% endfor %} 37 |
IDGenderFirst NameLast Name
{{s.id}} 32 | {{s.first_name}}{{s.last_name}}
38 |
39 |
40 | 41 | New 42 | Save 43 | 44 | 45 | -------------------------------------------------------------------------------- /lab_02_Blueprints/utils/serialize.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | import pickle 3 | 4 | 5 | def serialize(object): 6 | return codecs.encode(pickle.dumps(object, pickle.HIGHEST_PROTOCOL), "base64").decode() 7 | 8 | 9 | def deserialize(object_string): 10 | return pickle.loads(codecs.decode(object_string.encode(), "base64")) 11 | -------------------------------------------------------------------------------- /lab_02_Building_Web_Applications_with_Flask/models.py: -------------------------------------------------------------------------------- 1 | class Teacher: 2 | def __init__(self, name, course, students={}): 3 | super().__init__() 4 | self.name = name 5 | self.course = course 6 | self.students = students 7 | 8 | 9 | class Student: 10 | def __init__(self, id, first_name, last_name, gender='MALE'): 11 | super().__init__() 12 | self.id = id 13 | self.first_name = first_name 14 | self.last_name = last_name 15 | self.gender = gender 16 | 17 | -------------------------------------------------------------------------------- /lab_02_Building_Web_Applications_with_Flask/serialize.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | import pickle 3 | 4 | 5 | def serialize(object): 6 | return codecs.encode(pickle.dumps(object, pickle.HIGHEST_PROTOCOL), "base64").decode() 7 | 8 | 9 | def deserialize(object_string): 10 | return pickle.loads(codecs.decode(object_string.encode(), "base64")) 11 | -------------------------------------------------------------------------------- /lab_02_Building_Web_Applications_with_Flask/templates/add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 |
id
First name
Last name
Gender 25 | 29 |
33 |
34 | 35 | -------------------------------------------------------------------------------- /lab_02_Building_Web_Applications_with_Flask/templates/edit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 |
id{{student.id}}
First name
Last name
Gender 25 | 29 |
32 | 33 |
34 | 35 | -------------------------------------------------------------------------------- /lab_02_Building_Web_Applications_with_Flask/templates/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Register 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
Name
Course
19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /lab_02_Building_Web_Applications_with_Flask/templates/save.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Saved 6 | 7 | 8 | 9 | Return to the students page 10 | 11 | -------------------------------------------------------------------------------- /lab_02_Building_Web_Applications_with_Flask/templates/students.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Students List 6 | 7 | 8 | 9 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
Student List
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {% for s in students: %} 36 | 37 | 38 | 39 | 40 | 42 | 43 | 44 | 45 | {% endfor %} 46 |
IDGenderFirst NameLast Name
{{s.id}} 41 | {{s.first_name}}{{s.last_name}}
47 |
48 |
49 | 50 | New 51 | Save 52 | 53 | 54 | -------------------------------------------------------------------------------- /lab_02_Building_Web_Applications_with_Flask/views.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from flask import request, render_template, Flask, redirect, url_for, make_response, session 4 | from lab_02_Building_Web_Applications_with_Flask.models import Teacher, Student 5 | from lab_02_Building_Web_Applications_with_Flask.serialize import deserialize, serialize 6 | 7 | app = Flask(__name__) 8 | 9 | 10 | @app.route('/', methods=['GET']) 11 | def index(): 12 | teacher = retrieve_teacher() 13 | if teacher is None: 14 | return redirect(url_for("register")) 15 | 16 | return redirect(url_for("show_students")) 17 | 18 | 19 | @app.route('/register', methods=["POST", "GET"]) 20 | def register(): 21 | if request.method == 'GET': 22 | return render_template("register.html") 23 | else: 24 | name = request.form.get("name") 25 | course = request.form.get("course") 26 | teacher = Teacher(name, course) 27 | 28 | session["_teacher"] = serialize(teacher) 29 | return redirect(url_for("index")) 30 | 31 | 32 | @app.route('/students', methods=["GET"]) 33 | def show_students(): 34 | teacher = retrieve_teacher() 35 | if teacher is None: 36 | return redirect("register") 37 | else: 38 | return render_template("students.html", students=teacher.students.values()) 39 | 40 | 41 | @app.route('/add', methods=["POST", "GET"]) 42 | def add(): 43 | if request.method == 'GET': 44 | return render_template("add.html") 45 | else: 46 | id = request.form.get("id") 47 | firstname = request.form.get("firstname") 48 | lastname = request.form.get("lastname") 49 | gender = request.form.get("gender") 50 | 51 | teacher = retrieve_teacher() 52 | teacher.students[id] = Student(id, firstname, lastname, gender) 53 | session['_teacher'] = serialize(teacher) 54 | 55 | return redirect(url_for("show_students")) 56 | 57 | 58 | @app.route('/delete/', methods=["GET", "POST", "DELETE"]) 59 | def delete(id): 60 | teacher = retrieve_teacher() 61 | teacher.students.pop(id) 62 | session['_teacher'] = serialize(teacher) 63 | 64 | return redirect(url_for("show_students")) 65 | 66 | 67 | @app.route('/edit/', methods=["POST", "GET"]) 68 | def edit(id): 69 | teacher = retrieve_teacher() 70 | student = teacher.students.pop(id) 71 | 72 | if request.method == 'GET': 73 | return render_template("edit.html", student=student) 74 | else: 75 | student.first_name = request.form.get("firstname") 76 | student.last_name = request.form.get("lastname") 77 | student.gender = request.form.get("gender") 78 | 79 | teacher.students[id] = student 80 | session['_teacher'] = serialize(teacher) 81 | return redirect(url_for("show_students")) 82 | 83 | 84 | @app.route('/save') 85 | def save(): 86 | serialized_teacher = session.get("_teacher") 87 | resp = make_response(render_template("save.html")) 88 | if serialized_teacher is not None: 89 | expire_date = datetime.datetime.now() + datetime.timedelta(days=90) 90 | resp.set_cookie("_teacher", serialized_teacher, expires=expire_date) 91 | 92 | return resp 93 | 94 | 95 | def retrieve_teacher(): 96 | serialized_teacher = session.get("_teacher") 97 | if serialized_teacher is None: 98 | serialized_teacher = request.cookies.get('_teacher') 99 | 100 | if serialized_teacher is not None: 101 | return deserialize(serialized_teacher) 102 | 103 | return None 104 | 105 | 106 | if __name__ == "__main__": 107 | app.secret_key = 'SPECIFY_YOUR_OWN_SECRET_KEY' 108 | app.config['SESSION_TYPE'] = 'filesystem' 109 | app.run() -------------------------------------------------------------------------------- /lab_03_RESTful_via_Flask/main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask import jsonify 3 | from flask_restful import reqparse 4 | 5 | app = Flask(__name__) 6 | database = [] 7 | 8 | 9 | class Student: 10 | def __init__(self, name, grade): 11 | self.name = name 12 | self.grade = grade 13 | 14 | 15 | class Statistics: 16 | min = None 17 | max = None 18 | average = 0 19 | num_of_students = 0 20 | 21 | 22 | def statistics(): 23 | """ 24 | This function gets through the all student objects in the database 25 | and calculates min, max, average, and total number of students. 26 | :return: Statistics 27 | """ 28 | stats = Statistics() 29 | stats.num_of_students = len(database) 30 | 31 | if stats.num_of_students == 0: 32 | return stats 33 | 34 | stats.max = database[0].grade 35 | stats.min = database[0].grade 36 | sum = 0 37 | for student in database: 38 | sum += student.grade 39 | if student.grade < stats.min: 40 | stats.min = student.grade 41 | if student.grade > stats.max: 42 | stats.max = student.grade 43 | 44 | stats.average = sum / stats.num_of_students 45 | return stats 46 | 47 | 48 | @app.route("/students", methods=['POST']) 49 | def add_student(): 50 | parser = reqparse.RequestParser() 51 | parser.add_argument('name', type=str) 52 | parser.add_argument('grade', type=int) 53 | args = parser.parse_args() 54 | 55 | name = args.get("name") 56 | grade = args.get("grade") 57 | 58 | database.append(Student(name, grade)) 59 | return jsonify(studentName= name),200 60 | 61 | 62 | @app.route("/students", methods=['GET']) 63 | def get_students(): 64 | response = jsonify([st.__dict__ for st in database]) 65 | response.headers._list.append(('Access-Control-Allow-Origin', '*')) 66 | return response 67 | 68 | 69 | @app.route("/students/", methods=['GET']) 70 | def get_student(name): 71 | for st in database: 72 | if st.name == name: 73 | return jsonify(st.__dict__) 74 | 75 | return jsonify(name=False), 404 76 | 77 | 78 | @app.route("/students/", methods=['DELETE']) 79 | def delete_student(name): 80 | for st in database: 81 | if st.name == name: 82 | database.remove(st) 83 | return jsonify(studentName=name), 200 84 | return jsonify(studentName=False), 200 85 | 86 | 87 | @app.route("/students/", methods=['POST']) 88 | def update_student(name): 89 | parser = reqparse.RequestParser() 90 | parser.add_argument('grade', type=int) 91 | args = parser.parse_args() 92 | grade = args.get("grade") 93 | 94 | for st in database: 95 | if st.name == name: 96 | database.remove(st) 97 | database.append(Student(name, grade)) 98 | return jsonify(studentName=name, studentGrade=grade), 201 99 | 100 | return jsonify(studentName=False), 404 101 | 102 | 103 | @app.route("/statistics", methods=['GET']) 104 | def get_statistics(): 105 | return jsonify(statistics().__dict__) 106 | 107 | 108 | if __name__ == "__main__": 109 | app.run() 110 | -------------------------------------------------------------------------------- /lab_03_RESTful_via_Flask/print_request_headers.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, jsonify 2 | import dicttoxml 3 | 4 | app = Flask(__name__) 5 | 6 | 7 | @app.route("/") 8 | def print_headers(): 9 | # Print the KEY-VALUES in the request header 10 | print(request.headers) 11 | 12 | # Find & return the header key-values 13 | headers = {} 14 | for h in request.headers.environ: 15 | header_key = h.replace("HTTP_", "") 16 | header_value = request.headers.get(header_key) 17 | if header_value is not None: 18 | headers[header_key] = header_value 19 | 20 | client_accepted_response_format = headers.get('ACCEPT') 21 | if client_accepted_response_format == "text/xml": 22 | return dicttoxml.dicttoxml(headers), 200, {"Content-Type": "text/xml"} 23 | 24 | return jsonify(headers) 25 | 26 | 27 | if __name__ == '__main__': 28 | app.run(debug=True) 29 | -------------------------------------------------------------------------------- /lab_04_RESTful_Client/delete_requests.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | john = { 4 | "name": "John", 5 | "grade": 95 6 | } 7 | URL = 'http://localhost:5000/students/' + john["name"] 8 | result = requests.delete(URL, headers={"Content-Type": "application/json"}) 9 | if not result.ok: 10 | print("status code", result.status_code) 11 | print(result.text) 12 | quit() 13 | else: 14 | print(result.text) 15 | -------------------------------------------------------------------------------- /lab_04_RESTful_Client/get_requests.py: -------------------------------------------------------------------------------- 1 | import requests 2 | response = requests.get("http://localhost:5000/statistics", params=None) 3 | print("statistics:", response.json()) 4 | -------------------------------------------------------------------------------- /lab_04_RESTful_Client/post_requests.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | john = { 4 | "name": "John", 5 | "grade": 95 6 | } 7 | 8 | result = requests.post("http://localhost:5000/students", json=john, headers={"Content-Type": "application/json"}) 9 | if not result.ok: 10 | print("status code", result.status_code) 11 | print(result.text) 12 | quit() 13 | else: 14 | print(result.text) 15 | 16 | susan = { 17 | "name": "Susan", 18 | "grade": 100 19 | } 20 | 21 | result = requests.post("http://localhost:5000/students", json=susan) 22 | if not result.ok: 23 | print("status code", result.status_code) 24 | print(result.text) 25 | quit() 26 | else: 27 | print(result.text) 28 | 29 | result = requests.get("http://localhost:5000/statistics", params=None) 30 | print("statistics : ", result.json()) 31 | -------------------------------------------------------------------------------- /lab_04_RESTful_Client/receive.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 87 |
88 |

Add a New Student:

89 |
90 | 91 | 92 | 93 |
94 |
95 |
96 |

Update Student Info

97 |
98 | 99 | 100 | 101 |
102 |
103 |

Delete Student

104 |
105 | 106 | 107 |
108 |
109 |

List all students:

110 | 111 |
112 | 113 |
114 | 115 | -------------------------------------------------------------------------------- /lab_04_RESTful_Client/show_students.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Show Students 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /lab_05_Visualization_via_D3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 23 | 24 | 104 | -------------------------------------------------------------------------------- /lab_05_Visualization_via_D3/main.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | from flask import Flask 3 | import datetime 4 | import threading 5 | import time 6 | import psutil as psutil 7 | from jsonpickle import json 8 | 9 | app = Flask(__name__) 10 | mem_history = deque(maxlen=60) 11 | 12 | 13 | def record_mem(): 14 | while True: 15 | if len(mem_history) == 60: 16 | mem_history.pop() 17 | date = datetime.datetime.now() 18 | date = int(date.timestamp()) 19 | mem_history.append({'date': date, 'memory_usage': psutil.virtual_memory().percent}) 20 | time.sleep(10) 21 | 22 | 23 | t = threading.Thread(target=record_mem) 24 | t.daemon = True 25 | t.start() 26 | 27 | 28 | @app.route("/mem", methods=['GET']) 29 | def get_memory_history(): 30 | history = list(mem_history) 31 | # to allow external access to the endpoint you need to add 'Access-Control-Allow-Origin': '*' to the headers 32 | return json.dumps(history), 200, {'Access-Control-Allow-Origin': '*'} 33 | 34 | 35 | if __name__ == '__main__': 36 | app.run(debug=True) 37 | -------------------------------------------------------------------------------- /lab_06_Authentication/auth.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | 3 | from flask import request, jsonify 4 | from flask_restful import abort 5 | from itsdangerous import (TimedJSONWebSignatureSerializer as Serializer) 6 | 7 | SECRET_KEY = "A RANDOM KEY" 8 | 9 | 10 | def authenticate_by_token(token): 11 | if token is None: 12 | return False 13 | s = Serializer(SECRET_KEY) 14 | try: 15 | username = s.loads(token.encode()) 16 | if username == 'admin': 17 | return True 18 | except: 19 | return False 20 | 21 | return False 22 | 23 | 24 | def login_required(f, message="You are not authorized"): 25 | @wraps(f) 26 | def decorated_function(*args, **kwargs): 27 | 28 | token = request.headers.get("AUTH_TOKEN") 29 | if authenticate_by_token(token): 30 | return f(*args, **kwargs) 31 | 32 | return jsonify(message=message), 401 33 | # abort(401, message=message) 34 | 35 | return decorated_function 36 | -------------------------------------------------------------------------------- /lab_06_Authentication/main.py: -------------------------------------------------------------------------------- 1 | from lab_06_Authentication.auth import login_required 2 | from lab_06_Authentication.auth import SECRET_KEY 3 | from flask import Flask 4 | from flask import jsonify 5 | from flask_restful import reqparse 6 | from itsdangerous import (TimedJSONWebSignatureSerializer as Serializer) 7 | 8 | 9 | app = Flask(__name__) 10 | database = [] 11 | 12 | 13 | class Student: 14 | def __init__(self, name, grade): 15 | self.name = name 16 | self.grade = grade 17 | 18 | 19 | class Statistics: 20 | min = None 21 | max = None 22 | average = 0 23 | num_of_students = 0 24 | 25 | 26 | def statistics(): 27 | """ 28 | This function gets through the all student objects in the database 29 | and calculates min, max, average, and total number of students. 30 | :return: Statistics 31 | """ 32 | stats = Statistics() 33 | stats.num_of_students = len(database) 34 | 35 | if stats.num_of_students == 0: 36 | return stats 37 | 38 | stats.max = database[0].grade 39 | stats.min = database[0].grade 40 | sum = 0 41 | for student in database: 42 | sum += student.grade 43 | if student.grade < stats.min: 44 | stats.min = student.grade 45 | if student.grade > stats.max: 46 | stats.max = student.grade 47 | 48 | stats.average = sum / stats.num_of_students 49 | return stats 50 | 51 | 52 | @app.route("/students", methods=['POST']) 53 | @login_required 54 | def add_student(): 55 | parser = reqparse.RequestParser() 56 | parser.add_argument('name', type=str) 57 | parser.add_argument('grade', type=int) 58 | args = parser.parse_args() 59 | 60 | name = args.get("name") 61 | grade = args.get("grade") 62 | 63 | database.append(Student(name, grade)) 64 | return jsonify(studentName=name), 200 65 | 66 | 67 | @app.route("/students", methods=['GET']) 68 | @login_required 69 | def get_students(): 70 | response = jsonify([st.__dict__ for st in database]) 71 | # response.headers._list.append(('Access-Control-Allow-Origin', '*')) 72 | return response 73 | 74 | 75 | @app.route("/students/", methods=['GET']) 76 | @login_required 77 | def get_student(name): 78 | for st in database: 79 | if st.name == name: 80 | return jsonify(st.__dict__) 81 | 82 | return jsonify(name=False), 404 83 | 84 | 85 | @app.route("/students/", methods=['DELETE']) 86 | @login_required 87 | def delete_student(name): 88 | for st in database: 89 | if st.name == name: 90 | database.remove(st) 91 | return jsonify(studentName=name), 200 92 | return jsonify(studentName=False), 200 93 | 94 | 95 | @app.route("/students/", methods=['POST']) 96 | @login_required 97 | def update_student(name): 98 | parser = reqparse.RequestParser() 99 | parser.add_argument('grade', type=int) 100 | args = parser.parse_args() 101 | grade = args.get("grade") 102 | 103 | for st in database: 104 | if st.name == name: 105 | database.remove(st) 106 | database.append(Student(name, grade)) 107 | return jsonify(studentName=name, studentGrade=grade), 201 108 | 109 | return jsonify(studentName=False), 404 110 | 111 | 112 | @app.route("/statistics", methods=['GET']) 113 | @login_required 114 | def get_statistics(): 115 | return jsonify(statistics().__dict__) 116 | 117 | 118 | @app.route("/auth", methods=['GET']) 119 | def generate_token(): 120 | parser = reqparse.RequestParser() 121 | parser.add_argument('username', type=str) 122 | parser.add_argument('password', type=str) 123 | args = parser.parse_args() 124 | 125 | username = args.get("username") 126 | password = args.get("password") 127 | 128 | s = Serializer(SECRET_KEY, expires_in=600) 129 | token = s.dumps(username) 130 | 131 | if username == 'admin' and password == 'admin': 132 | return token.decode() 133 | 134 | return 404 135 | 136 | 137 | if __name__ == "__main__": 138 | app.run() 139 | -------------------------------------------------------------------------------- /lab_07_MongoDB/dbtest.py: -------------------------------------------------------------------------------- 1 | from mongoengine import connect 2 | 3 | from lab_07_MongoDB.models import Teacher, Student 4 | 5 | from mongoengine import connect 6 | from lab_07_MongoDB.models import Teacher, Student 7 | 8 | 9 | def save_information(): 10 | t1 = Teacher(1, 'Helen', 'Paik', [Student(1, "Tom", " Ainsley")]) 11 | t2 = Teacher(2, 'John', 'Hardy') 12 | connect('teacher') # add teachers to the database 13 | t1.save() 14 | t2.save() 15 | 16 | 17 | def get_all_teachers(): 18 | connect('teacher') 19 | for t in Teacher.objects: 20 | print(t.id, t.name) 21 | 22 | 23 | def get_one_teacher(): 24 | connect('teacher') 25 | for t in Teacher.objects(id=1): 26 | print(t.id, t.name) 27 | 28 | 29 | def update_teacher_info(): 30 | connect('teacher') 31 | Teacher.objects(id=2).update(name='George') 32 | 33 | 34 | def delete_teacher_info(): 35 | connect('teacher') 36 | Teacher.objects(id=2).Delete() 37 | 38 | 39 | if __name__ == '__main__': 40 | save_information() 41 | get_all_teachers() 42 | delete_teacher_info() 43 | 44 | 45 | -------------------------------------------------------------------------------- /lab_07_MongoDB/models.py: -------------------------------------------------------------------------------- 1 | from mongoengine import StringField, IntField, Document, EmbeddedDocument, ListField, EmbeddedDocumentField 2 | 3 | 4 | class Student(EmbeddedDocument): 5 | id = IntField(required=True, primary_key=True) 6 | first_name = StringField(required=True, max_length=50) 7 | last_name = StringField(required=True, max_length=50) 8 | gender = StringField(required=True, max_length=50) 9 | 10 | def __init__(self, id, first_name, last_name, gender='MALE', *args, **kwargs): 11 | super().__init__(*args, **kwargs) 12 | self.id = id 13 | self.first_name = first_name 14 | self.last_name = last_name 15 | self.gender = gender 16 | 17 | 18 | class Teacher(Document): 19 | id = IntField(required=True, primary_key=True) 20 | name = StringField(required=True, max_length=50) 21 | course = StringField(required=True, max_length=50) 22 | students = ListField(EmbeddedDocumentField(Student)) 23 | 24 | def __init__(self, id, name, course, students=[], *args, **values): 25 | super().__init__(*args, **values) 26 | self.id = id 27 | self.name = name 28 | self.course = course 29 | self.students = students 30 | -------------------------------------------------------------------------------- /lab_08_ORM/database.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import scoped_session, sessionmaker 4 | 5 | Base = declarative_base() 6 | engine = create_engine('sqlite:///:memory:', echo=True) 7 | db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) 8 | Base.query = db_session.query_property() 9 | 10 | 11 | def init_db(): 12 | # create tables 13 | Base.metadata.create_all(bind=engine) 14 | -------------------------------------------------------------------------------- /lab_08_ORM/dbtest.py: -------------------------------------------------------------------------------- 1 | from lab_08_ORM.database import db_session, init_db 2 | from lab_08_ORM.models import Teacher, Student 3 | 4 | init_db() 5 | 6 | t1 = Teacher('Helen', 'Paik', {1: Student(1, "Ali", "Hasan")}) 7 | t2 = Teacher('John', 'Hard') 8 | 9 | # add teachers to the database 10 | db_session.add(t1) 11 | db_session.add(t2) 12 | 13 | # commit the changes 14 | db_session.commit() 15 | 16 | # query the database 17 | for t in Teacher.query.all(): 18 | print("Teacher:", t.name, " Number of Students:", len(t.students)) 19 | -------------------------------------------------------------------------------- /lab_08_ORM/models.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import Column, Integer, String 2 | from sqlalchemy import PickleType 3 | 4 | from lab_08_ORM.database import Base 5 | 6 | 7 | class Teacher(Base): 8 | __tablename__ = 'teachers' 9 | 10 | id = Column(Integer, primary_key=True, autoincrement=True) 11 | name = Column(String) 12 | course = Column(String) 13 | students = Column(PickleType) 14 | 15 | def __init__(self, name, course, students={}): 16 | super().__init__() 17 | self.name = name 18 | self.course = course 19 | self.students = students 20 | 21 | 22 | class Student: 23 | def __init__(self, id, first_name, last_name, gender='MALE'): 24 | super().__init__() 25 | self.id = id 26 | self.first_name = first_name 27 | self.last_name = last_name 28 | self.gender = gender 29 | --------------------------------------------------------------------------------