commit dfb0da0555b7c4572426dfe8ce7ac34d7c77faff Author: Malar Kannan Date: Thu Aug 31 14:14:47 2017 +0530 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7ecbf91 --- /dev/null +++ b/.gitignore @@ -0,0 +1,104 @@ + +# Created by https://www.gitignore.io/api/python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# End of https://www.gitignore.io/api/python diff --git a/SPEC.md b/SPEC.md new file mode 100644 index 0000000..3cd9d11 --- /dev/null +++ b/SPEC.md @@ -0,0 +1,17 @@ +Problem Statement: + +Build a Web Application Backend (No clientside required) for student attendance management. +There should be authentication support with basic session management. +Database usage: MySql or MongoDb. +Web Application: Any python web framework can be used. +Other Libraries: Upto your needs. + +Basic Functionality: +* Login +* Update attendance for an entire class / student. +* Get attendance for a student given a time period. +* Logout + +Pointers: +* Good thought should be put in the creation of the API's. +* Code Quality diff --git a/server.py b/server.py new file mode 100644 index 0000000..cb1f181 --- /dev/null +++ b/server.py @@ -0,0 +1,114 @@ +from flask import Flask,Blueprint,request,Response +from flask_sqlalchemy import SQLAlchemy +from flask_security import SQLAlchemyUserDatastore,UserMixin,RoleMixin,login_required,current_user,Security +from flask_restless import APIManager,ProcessingException +from enum import Enum,unique +import json + +app = Flask(__name__) +app.config['DEBUG'] = True +app.config['SECRET_KEY'] = 'super-secret' +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/db.sqlite' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +app.config['DEFAULT_MAIL_SENDER'] = 'info@example.com' +app.config['SECURITY_PASSWORD_SALT'] = 'uaisfyasiduyaisiuf' + + + +db = SQLAlchemy(app) + +roles_users = db.Table('roles_users', + db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), + db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))) + +class Role(db.Model, RoleMixin): + id = db.Column(db.Integer(), primary_key=True) + name = db.Column(db.String(80), unique=True) + description = db.Column(db.String(255)) + +class User(db.Model, UserMixin): + id = db.Column(db.Integer, primary_key=True) + email = db.Column(db.String(255), unique=True) + password = db.Column(db.String(255)) + active = db.Column(db.Boolean()) + confirmed_at = db.Column(db.DateTime()) + roles = db.relationship('Role', secondary=roles_users, + backref=db.backref('users', lazy='dynamic')) + +# class ClassSession(db.Model): +# id = db.Column(db.Integer, primary_key=True) +# name = db.Column(db.String(255), unique=True) +# confirmed_at = db.Column(db.DateTime()) + +@unique +class Presence(Enum): + """docstring for ResultType.""" + PRESENT,ABSENT,SICK,VACATION = range(4) + +class Gradeclass(db.Model): + id = db.Column(db.Integer, primary_key=True) + class_name = db.Column(db.String(255)) + +class Student(db.Model): + id = db.Column(db.Integer, primary_key=True) + student_name = db.Column(db.String(255)) + gradeclass_id = db.Column(db.Integer, db.ForeignKey('gradeclass.id')) + gradeclass = db.relationship('Gradeclass',backref=db.backref('gradeclass', lazy='dynamic')) + +class StudentAttendance(db.Model): + id = db.Column(db.BigInteger, primary_key=True) + student_id = db.Column(db.Integer, db.ForeignKey('student.id')) + gradeclass_id = db.Column(db.Integer, db.ForeignKey('gradeclass.id')) + time = db.Column(db.DateTime()) + presence = db.Column(db.Enum(Presence)) + student = db.relationship('Student',backref=db.backref('student', lazy='dynamic')) + gradeclass = db.relationship('Gradeclass',backref=db.backref('gradeclass', lazy='dynamic')) + + +user_datastore = SQLAlchemyUserDatastore(db, User, Role) +security = Security(app, user_datastore) + +def auth_func(*args, **kwargs): + # if not current_user.is_authenticated: + # raise ProcessingException(description='Not authenticated', code=401) + return True + +verify_logged_id = dict(GET_SINGLE=[auth_func],GET_MANY=[auth_func]) + +manager = APIManager(app, flask_sqlalchemy_db=db) +manager.create_api(Student, methods=['GET','PUT'],results_per_page=5,preprocessors=verify_logged_id) +manager.create_api(Gradeclass, methods=['GET','PUT'],results_per_page=5,preprocessors=verify_logged_id) + +@app.before_first_request +def create_user(): + try: + db.drop_all() + db.create_all() + user_datastore.create_user(email='user@example.com', password='password') + db.session.commit() + except: + pass + + +def api_resp(data,code=200): + return Response(response=data, + status=code, + mimetype="application/json") + +@app.route('/api/attendance/',methods=['GET']) +# @login_required +def update_attendance(update_type): + value = request.args.get('presence',None) + object_id = request.args.get('identifier',None) + if update_type == 'class': + + elif update_type == 'student': + data= json.dumps({'status':'updated'}) + return api_resp(data) + +@app.route('/') +def home(): + return 'hello' + +if __name__ == '__main__': + app.run()