Theory903 commited on
Commit
3cf589c
·
1 Parent(s): 5c9b676

Add application file

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Procfile +1 -0
  2. README.md +1 -5
  3. __pycache__/config.cpython-311.pyc +0 -0
  4. __pycache__/config.cpython-38.pyc +0 -0
  5. __pycache__/main.cpython-37.pyc +0 -0
  6. app.db +0 -0
  7. app/__init__.py +11 -0
  8. app/__pycache__/__init__.cpython-311.pyc +0 -0
  9. app/__pycache__/__init__.cpython-37.pyc +0 -0
  10. app/__pycache__/__init__.cpython-38.pyc +0 -0
  11. app/__pycache__/forms.cpython-311.pyc +0 -0
  12. app/__pycache__/forms.cpython-37.pyc +0 -0
  13. app/__pycache__/forms.cpython-38.pyc +0 -0
  14. app/__pycache__/models.cpython-311.pyc +0 -0
  15. app/__pycache__/models.cpython-38.pyc +0 -0
  16. app/__pycache__/routes.cpython-311.pyc +0 -0
  17. app/__pycache__/routes.cpython-37.pyc +0 -0
  18. app/__pycache__/routes.cpython-38.pyc +0 -0
  19. app/forms.py +34 -0
  20. app/models.py +30 -0
  21. app/routes.py +87 -0
  22. app/static/css/mob-styles.css +178 -0
  23. app/static/css/styles.css +358 -0
  24. app/static/images/boy-with-glasses.jpg +0 -0
  25. app/static/images/check-circle-solid.svg +1 -0
  26. app/static/images/home.jpg +0 -0
  27. app/static/images/kids-studying-from-home.gif +0 -0
  28. app/templates/base.html +42 -0
  29. app/templates/index.html +18 -0
  30. app/templates/login.html +42 -0
  31. app/templates/question.html +22 -0
  32. app/templates/register.html +81 -0
  33. app/templates/score.html +19 -0
  34. config.py +10 -0
  35. main.py +5 -0
  36. migrations/README +1 -0
  37. migrations/__pycache__/env.cpython-38.pyc +0 -0
  38. migrations/alembic.ini +45 -0
  39. migrations/env.py +96 -0
  40. migrations/script.py.mako +24 -0
  41. migrations/versions/4f3f4537bb29_users_table.py +38 -0
  42. migrations/versions/59069a416ef2_question_table.py +41 -0
  43. migrations/versions/9c77048e7767_questions_table.py +43 -0
  44. migrations/versions/__pycache__/4f3f4537bb29_users_table.cpython-38.pyc +0 -0
  45. migrations/versions/__pycache__/59069a416ef2_question_table.cpython-38.pyc +0 -0
  46. migrations/versions/__pycache__/9c77048e7767_questions_table.cpython-38.pyc +0 -0
  47. migrations/versions/__pycache__/a635661f4a03_users_table.cpython-38.pyc +0 -0
  48. migrations/versions/__pycache__/e96865e4fa62_users_added_marks.cpython-38.pyc +0 -0
  49. migrations/versions/a635661f4a03_users_table.py +38 -0
  50. migrations/versions/e96865e4fa62_users_added_marks.py +42 -0
Procfile ADDED
@@ -0,0 +1 @@
 
 
1
+ web: gunicorn main:app
README.md CHANGED
@@ -1,11 +1,7 @@
1
- ---
2
  title: OIST QUIZ APP
3
  emoji: 📊
4
  colorFrom: indigo
5
  colorTo: indigo
6
  sdk: docker
7
  pinned: false
8
- license: apache-2.0
9
- ---
10
-
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  title: OIST QUIZ APP
2
  emoji: 📊
3
  colorFrom: indigo
4
  colorTo: indigo
5
  sdk: docker
6
  pinned: false
7
+ license: apache-2.0
 
 
 
__pycache__/config.cpython-311.pyc ADDED
Binary file (1.04 kB). View file
 
__pycache__/config.cpython-38.pyc ADDED
Binary file (628 Bytes). View file
 
__pycache__/main.cpython-37.pyc ADDED
Binary file (143 Bytes). View file
 
app.db ADDED
Binary file (41 kB). View file
 
app/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask
2
+ from config import Config
3
+ from flask_sqlalchemy import SQLAlchemy
4
+ from flask_migrate import Migrate
5
+
6
+ app = Flask(__name__)
7
+ app.config.from_object(Config)
8
+ db = SQLAlchemy(app)
9
+ migrate = Migrate(app, db)
10
+
11
+ from app import routes
app/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (672 Bytes). View file
 
app/__pycache__/__init__.cpython-37.pyc ADDED
Binary file (253 Bytes). View file
 
app/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (426 Bytes). View file
 
app/__pycache__/forms.cpython-311.pyc ADDED
Binary file (3.23 kB). View file
 
app/__pycache__/forms.cpython-37.pyc ADDED
Binary file (662 Bytes). View file
 
app/__pycache__/forms.cpython-38.pyc ADDED
Binary file (1.95 kB). View file
 
app/__pycache__/models.cpython-311.pyc ADDED
Binary file (2.89 kB). View file
 
app/__pycache__/models.cpython-38.pyc ADDED
Binary file (1.57 kB). View file
 
app/__pycache__/routes.cpython-311.pyc ADDED
Binary file (6.44 kB). View file
 
app/__pycache__/routes.cpython-37.pyc ADDED
Binary file (2.77 kB). View file
 
app/__pycache__/routes.cpython-38.pyc ADDED
Binary file (3 kB). View file
 
app/forms.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask_wtf import FlaskForm
2
+ from wtforms import StringField, PasswordField, BooleanField, SubmitField, RadioField
3
+ from wtforms.validators import ValidationError, DataRequired, Email, EqualTo
4
+ from wtforms.ext.sqlalchemy.fields import QuerySelectField
5
+
6
+ from app.models import User
7
+
8
+ class LoginForm(FlaskForm):
9
+ username = StringField('Username', validators=[DataRequired()])
10
+ password = PasswordField('Password', validators=[DataRequired()])
11
+ remember_me = BooleanField('Remember Me')
12
+ submit = SubmitField('Login')
13
+
14
+ class RegistrationForm(FlaskForm):
15
+ username = StringField('Username', validators=[DataRequired()])
16
+ email = StringField('Email', validators=(DataRequired(), Email()))
17
+ password = PasswordField('Password', validators=[DataRequired()])
18
+ password2 = PasswordField('Confirm Password',
19
+ validators=(DataRequired(), EqualTo('password')))
20
+ submit = SubmitField('Register')
21
+
22
+ def validate_username(self, username):
23
+ user = User.query.filter_by(username=username.data).first()
24
+ if user is not None:
25
+ raise ValidationError('Username already exists')
26
+
27
+ def validate_email(self, email):
28
+ user = User.query.filter_by(email=email.data).first()
29
+ if user is not None:
30
+ raise ValidationError('Email already exists.')
31
+
32
+ class QuestionForm(FlaskForm):
33
+ options = RadioField('Options: ', validators=[DataRequired()], default=1)
34
+ submit = SubmitField('Next')
app/models.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from app import db
2
+ from werkzeug.security import generate_password_hash, check_password_hash
3
+
4
+ class User(db.Model):
5
+ id = db.Column(db.Integer, primary_key=True)
6
+ username = db.Column(db.String(64), index=True, unique=True)
7
+ email = db.Column(db.String(120), index=True, unique=True)
8
+ password_hash = db.Column(db.String(128))
9
+ marks = db.Column(db.Integer, index=True)
10
+
11
+ def __repr__(self):
12
+ return '<User {}>'.format(self.username)
13
+
14
+ def set_password(self, password):
15
+ self.password_hash = generate_password_hash(password)
16
+
17
+ def check_password(self, password):
18
+ return check_password_hash(self.password_hash, password)
19
+
20
+ class Questions(db.Model):
21
+ q_id = db.Column(db.Integer, primary_key=True)
22
+ ques = db.Column(db.String(350), unique=True)
23
+ a = db.Column(db.String(100))
24
+ b = db.Column(db.String(100))
25
+ c = db.Column(db.String(100))
26
+ d = db.Column(db.String(100))
27
+ ans = db.Column(db.String(100))
28
+
29
+ def __repr__(self):
30
+ return '<Question: {}>'.format(self.ques)
app/routes.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from app import app
2
+ from flask import render_template, request, redirect, url_for, session, g, flash
3
+ from werkzeug.urls import url_parse
4
+ from app.forms import LoginForm, RegistrationForm, QuestionForm
5
+ from app.models import User, Questions
6
+ from app import db
7
+
8
+
9
+ @app.before_request
10
+ def before_request():
11
+ g.user = None
12
+
13
+ if 'user_id' in session:
14
+ user = User.query.filter_by(id=session['user_id']).first()
15
+ g.user = user
16
+
17
+ @app.route('/')
18
+ def home():
19
+ return render_template('index.html', title='Home')
20
+
21
+ @app.route('/login', methods=['GET', 'POST'])
22
+ def login():
23
+ form = LoginForm()
24
+ if form.validate_on_submit():
25
+ user = User.query.filter_by(username=form.username.data).first()
26
+ if user is None or not user.check_password(form.password.data):
27
+ return redirect(url_for('login'))
28
+ session['user_id'] = user.id
29
+ session['marks'] = 0
30
+ next_page = request.args.get('next')
31
+ if not next_page or url_parse(next_page).netloc != '':
32
+ next_page = url_for('home')
33
+ return redirect(next_page)
34
+ return redirect(url_for('home'))
35
+ if g.user:
36
+ return redirect(url_for('home'))
37
+ return render_template('login.html', form=form, title='Login')
38
+
39
+ @app.route('/register', methods=['GET', 'POST'])
40
+ def register():
41
+ form = RegistrationForm()
42
+ if form.validate_on_submit():
43
+ user = User(username=form.username.data, email=form.password.data)
44
+ user.set_password(form.password.data)
45
+ db.session.add(user)
46
+ db.session.commit()
47
+ session['user_id'] = user.id
48
+ session['marks'] = 0
49
+ return redirect(url_for('home'))
50
+ if g.user:
51
+ return redirect(url_for('home'))
52
+ return render_template('register.html', title='Register', form=form)
53
+
54
+
55
+
56
+ @app.route('/question/<int:id>', methods=['GET', 'POST'])
57
+ def question(id):
58
+ form = QuestionForm()
59
+ q = Questions.query.filter_by(q_id=id).first()
60
+ if not q:
61
+ return redirect(url_for('score'))
62
+ if not g.user:
63
+ return redirect(url_for('login'))
64
+ if request.method == 'POST':
65
+ option = request.form['options']
66
+ if option == q.ans:
67
+ session['marks'] += 10
68
+ return redirect(url_for('question', id=(id+1)))
69
+ form.options.choices = [(q.a, q.a), (q.b, q.b), (q.c, q.c), (q.d, q.d)]
70
+ return render_template('question.html', form=form, q=q, title='Question {}'.format(id))
71
+
72
+
73
+ @app.route('/score')
74
+ def score():
75
+ if not g.user:
76
+ return redirect(url_for('login'))
77
+ g.user.marks = session['marks']
78
+ # db.session.commit()
79
+ return render_template('score.html', title='Final Score')
80
+
81
+ @app.route('/logout')
82
+ def logout():
83
+ if not g.user:
84
+ return redirect(url_for('login'))
85
+ session.pop('user_id', None)
86
+ session.pop('marks', None)
87
+ return redirect(url_for('home'))
app/static/css/mob-styles.css ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @media all and (max-width: 600px) {
2
+
3
+ nav {
4
+ /* height: 70px; */
5
+ padding: 2%;;
6
+ }
7
+
8
+ /* Home Page css */
9
+ .home-img{
10
+ width: auto;
11
+ height: 400px;
12
+ order: 1;
13
+ }
14
+
15
+ .home-div {
16
+ flex-direction: column-reverse;
17
+ }
18
+
19
+ .info-div{
20
+ align-items: center;
21
+ }
22
+
23
+ .info-div h1 {
24
+ font-weight: 700;
25
+ font-size: 25px;
26
+ }
27
+
28
+ .info-div h4 {
29
+ color: #fff;
30
+ font-weight: 600;
31
+ font-size: 18px;
32
+ text-align: center;
33
+ /* width: 95%; */
34
+ }
35
+
36
+ .home-div a {
37
+ color: #fff;
38
+ order: 2;
39
+ font-size: 18px;
40
+ margin-top: 30px;
41
+ border-radius: 30px;
42
+ padding: 15px;
43
+ margin-bottom: 7%;
44
+ }
45
+
46
+
47
+
48
+ /* Login page css */
49
+ .login-img {
50
+ display: none;
51
+ }
52
+
53
+ .login-form {
54
+ margin-top: 10%;
55
+ }
56
+
57
+ /* Sign UP page css */
58
+
59
+ .register-img{
60
+ display: none;
61
+ }
62
+
63
+ .register-main{
64
+ margin: 5%;
65
+ margin-top: 2%;
66
+ /* margin-top: 5%; */
67
+ }
68
+
69
+
70
+
71
+ /* Question Page CSS */
72
+
73
+ .ques-div{
74
+ font-size: 20px;
75
+ margin: 7%;
76
+ margin-top: 2%;
77
+ }
78
+
79
+ .qnum{
80
+ font-size: 25px;
81
+ }
82
+
83
+ .ques-heading{
84
+ font-size: 25px;
85
+ }
86
+
87
+ .options-div{
88
+ margin-top: 13%;
89
+ }
90
+
91
+ .options-div label{
92
+ font-size: 17px;
93
+ }
94
+ .sub-btn{
95
+ margin-left: auto;
96
+ margin-right: auto;
97
+ }
98
+
99
+
100
+
101
+ /* Score Page csss */
102
+ .score-main{
103
+ margin-top: 30px;
104
+ }
105
+
106
+ .highest-score{
107
+ margin-top: 30px;
108
+ font-size: 18px;
109
+ width: 80%;
110
+ }
111
+
112
+
113
+ .score-head {
114
+ font-size: 35px;
115
+ margin-top: 40px;
116
+ }
117
+
118
+ .score-circle {
119
+ border-width: 8px;
120
+ width: 120px;
121
+ height: 120px;
122
+ margin-top: 32px;
123
+ }
124
+
125
+ .score-circle h1{
126
+ font-size: 40px;
127
+ padding: 17px;
128
+ }
129
+
130
+ .congrats-cls{
131
+ margin-top: 35px;
132
+ font-size: 30px;
133
+ }
134
+
135
+ .redirect-links{
136
+ margin-top: 60px;
137
+ width: 70%;
138
+ }
139
+
140
+
141
+ }
142
+
143
+ .container,
144
+ .container-fluid,
145
+ .container-sm,
146
+ .container-md,
147
+ .container-lg,
148
+ .container-xl {
149
+ width: 100%;
150
+ padding-right: 15px;
151
+ padding-left: 15px;
152
+ margin-right: auto;
153
+ margin-left: auto;
154
+ }
155
+
156
+ @media (min-width: 576px) {
157
+ .container {
158
+ max-width: 540px;
159
+ }
160
+ }
161
+
162
+ @media (min-width: 768px) {
163
+ .container {
164
+ max-width: 720px;
165
+ }
166
+ }
167
+
168
+ @media (min-width: 992px) {
169
+ .container {
170
+ max-width: 960px;
171
+ }
172
+ }
173
+
174
+ @media (min-width: 1200px) {
175
+ .container {
176
+ max-width: 1140px;
177
+ }
178
+ }
app/static/css/styles.css ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body{
2
+ height: 100%;
3
+ font-family: 'Inter', sans-serif;
4
+ font-weight: 600;
5
+ background-color: #fff;
6
+ /* background-color: #71baed; */
7
+ }
8
+
9
+ .home-bg{
10
+ display: flex;
11
+ flex-direction: column;
12
+ }
13
+
14
+ .home-bg .home-div {
15
+ flex: 1;
16
+ }
17
+
18
+
19
+ /* Nav CSS */
20
+
21
+
22
+ nav {
23
+ display: flex;
24
+ justify-content: flex-end;
25
+ align-items: center;
26
+ background-color: #fff;
27
+ border-bottom: 1px solid #8b95bd;
28
+ /* height: 50px; */
29
+ padding: 0.8%;
30
+ }
31
+
32
+ .nav-links {
33
+ list-style: none;
34
+ margin-bottom: 0em;
35
+ }
36
+
37
+ .nav-links li{
38
+ display: inline-block;
39
+ padding: 0px 15px;
40
+ margin-left: 20px;
41
+ }
42
+
43
+ .nav-links li a{
44
+ transition: all 0.3s ease 0s;
45
+ text-decoration: none;
46
+ color: #3e4667;
47
+ }
48
+
49
+
50
+ /* Home page CSS */
51
+
52
+ .home-img{
53
+ width: auto;
54
+ height: 525px;
55
+ border-radius: 50%;
56
+ margin-right: 20px;
57
+ }
58
+
59
+ .home-div {
60
+ background-color: #71baed;
61
+ display: flex;
62
+ justify-content: space-around;
63
+ align-items: center;
64
+ flex-direction: row-reverse;
65
+ width: 100%;
66
+ height: auto;
67
+ margin-left: 0;
68
+ margin-right: 0;
69
+ }
70
+
71
+
72
+
73
+ .info-div{
74
+ display: flex;
75
+ flex-direction: column;
76
+ justify-content: space-around;
77
+ align-items: flex-start;
78
+ }
79
+
80
+ .info-div h1 {
81
+ color: #fff;
82
+ font-weight: 700;
83
+ font-size: 50px;
84
+ }
85
+
86
+ .info-div h4 {
87
+ color: #fff;
88
+ font-weight: 700;
89
+ }
90
+
91
+ .info-div a {
92
+ background-color: #fad500;
93
+ color: #fff;
94
+ font-size: 18px;
95
+ margin-top: 40px;
96
+ border-radius: 30px;
97
+ padding: 15px;
98
+ text-decoration: none;
99
+ }
100
+
101
+
102
+
103
+ /* Login Page CSS */
104
+
105
+ .login-main {
106
+ display: flex;
107
+ justify-content: space-between;
108
+ background-color: #fff;
109
+ }
110
+
111
+ .login-img {
112
+ width: 61%;
113
+ height: auto;
114
+ margin-top: 20px;
115
+ }
116
+
117
+ .login-form {
118
+ display: flex;
119
+ justify-content: center;
120
+ align-items: center;
121
+ flex: 1;
122
+ }
123
+
124
+ .login-intro{
125
+ margin-bottom: 50px;
126
+ margin-left: 7px;
127
+ color: #8e8e8e;
128
+ }
129
+
130
+ .login-intro h1{
131
+ font-weight: 800;
132
+ color: #000;
133
+ }
134
+
135
+
136
+
137
+ .form-para {
138
+ display: flex;
139
+ align-items: center;
140
+ flex-direction: row;
141
+ margin-bottom: 27px;
142
+ }
143
+
144
+ .form-para svg {
145
+ border: none;
146
+ margin-right: 20px;
147
+ padding: 5px;
148
+ fill: #8e8e8e;
149
+ }
150
+
151
+ .form-para input {
152
+ border: none;
153
+ }
154
+
155
+ .form-para input ::placeholder{
156
+ color: #8e8e8e;
157
+ }
158
+
159
+ .form-para p {
160
+ color: #8e8e8e;
161
+ font-weight: 400;
162
+ }
163
+ .form-para span {
164
+ margin-left: 15px;
165
+
166
+ }
167
+
168
+ .form-para p input{
169
+ margin-left: 100px;
170
+ }
171
+
172
+
173
+ /* Register Page css */
174
+
175
+
176
+
177
+ .register-main{
178
+ display: flex;
179
+ justify-content: center;
180
+ background-color: #fff;
181
+ align-items: center;
182
+ }
183
+
184
+ .register-img{
185
+ width: 44.2%;
186
+ height: auto;
187
+ }
188
+
189
+ .register-form {
190
+ margin-top: 7px;
191
+ display: flex;
192
+ justify-content: center;
193
+ align-items: center;
194
+ flex: 1;
195
+ }
196
+
197
+ .register-form p{
198
+ display: block;
199
+ margin-left: auto;
200
+ }
201
+
202
+ .register-intro{
203
+ margin-top: 28px;
204
+ margin-left: 7px;
205
+ color: #8e8e8e;
206
+ margin-bottom: 0px;
207
+ }
208
+
209
+ .register-intro h1{
210
+ font-weight: 800;
211
+ color: #000;
212
+ }
213
+
214
+
215
+
216
+
217
+
218
+ /* Question Page CSS */
219
+
220
+ .ques-div {
221
+ background-color: #fff;
222
+ display: flex;
223
+ justify-content: center;
224
+ align-items: center;
225
+ }
226
+
227
+ .qnum {
228
+ margin-top: 25px;
229
+ color: #989cad;
230
+ }
231
+
232
+ form hr {
233
+ border: 1px dashed #525976;
234
+ }
235
+
236
+
237
+ .ques-heading {
238
+ font-weight: 800;
239
+ margin-bottom: 33px;
240
+ /* color: #fff; */
241
+ color: #3e4667;
242
+ max-width: 100%;
243
+ }
244
+
245
+
246
+ .options-div li {
247
+ box-sizing: content-box;
248
+ display: flex;
249
+ justify-content: space-between;
250
+ align-items: center;
251
+ flex-direction: row-reverse;
252
+ border: 3px solid #989cad;
253
+ border-radius: 15px;
254
+ padding: 10px;
255
+ width: 95%;
256
+ height: 30px;
257
+ margin-bottom: 17px;
258
+ margin-top: 15px;
259
+ }
260
+
261
+ .options-div label{
262
+ font-size: 20px;
263
+ color: #3e4667;
264
+ margin-top: 7px;
265
+ }
266
+
267
+ /* .options-div input{
268
+ margin-top: 10px;
269
+ } */
270
+
271
+ .sub-btn {
272
+ display: block;
273
+ margin-left: auto;
274
+ }
275
+
276
+ .check-circle{
277
+ font-size: 1.4em;
278
+ color: #3e4667;
279
+ }
280
+
281
+ /* Scores Page CSS */
282
+
283
+ .score-main {
284
+ display: flex;
285
+ justify-content: space-between;
286
+ flex-direction: column;
287
+ align-items: center;
288
+ background-color: #fff;
289
+ }
290
+
291
+
292
+
293
+ .score-head {
294
+ font-weight: 600;
295
+ margin-top: 30px;
296
+ font-style: bold;
297
+ color: #49535f;
298
+
299
+ }
300
+
301
+ .score-circle {
302
+ display: flex;
303
+ align-items: center;
304
+ justify-content: center;
305
+ border: 10px solid #107eeb;
306
+ border-radius: 50%;
307
+ width: 140px;
308
+ height: 140px;
309
+ margin-top: 15px;
310
+ }
311
+
312
+ .score-circle h1{
313
+ font-size: 50px;
314
+ border-radius: 50%;
315
+ padding: 20px;
316
+
317
+ color: #49535f;
318
+ }
319
+
320
+ .congrats-cls{
321
+ margin-top: 15px;
322
+ font-style: bold;
323
+ color: #49535f;
324
+ }
325
+
326
+ .highest-score{
327
+ display: flex;
328
+ flex-flow: row nowrap;
329
+ justify-content: center;
330
+ align-items: center;
331
+ margin-top: 30px;
332
+ border: 50px;
333
+ background-color: #107eeb;
334
+ color: #fff;
335
+ border: 2px solid #107eeb;
336
+ border-radius: 100px;
337
+ padding: 5px;
338
+ font-size: 26px;
339
+ width: 40%;
340
+ }
341
+
342
+ .high-score-name {
343
+ background-color: #fff;
344
+ border: 2px solid #fff;
345
+ border-radius: 100px;
346
+ color: #49535f;
347
+ padding: 5px;
348
+ margin: 5px;
349
+ margin-left: 18px;
350
+ }
351
+
352
+ .redirect-links{
353
+ display: flex;
354
+ justify-content: space-between;
355
+ align-items: center;
356
+ margin-top: 50px;
357
+ width: 60%;
358
+ }
app/static/images/boy-with-glasses.jpg ADDED
app/static/images/check-circle-solid.svg ADDED
app/static/images/home.jpg ADDED
app/static/images/kids-studying-from-home.gif ADDED
app/templates/base.html ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <head>
3
+ {% if title %}
4
+ <title> {{ title }} </title>
5
+ {% else %}
6
+ <title> Default </title>
7
+ {% endif %}
8
+
9
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
10
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
11
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
12
+
13
+ <script src="https://kit.fontawesome.com/21d2eca3df.js" crossorigin="anonymous"></script>
14
+ <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
15
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
16
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
17
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
18
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/mob-styles.css') }}">
19
+ </head>
20
+ <body class="home-bg">
21
+ <nav>
22
+ <ul class="nav-links">
23
+ <li> <a href="{{ url_for('home') }}"> Home </a> </li>
24
+ {% if not g.user %}
25
+ <li> <a href="{{ url_for('login') }}"> Login </a> </li>
26
+ {% else %}
27
+ <li> <a href="{{ url_for('logout') }}"> Logout </a> </li>
28
+ {% endif %}
29
+ </ul>
30
+ </nav>
31
+ {% with messages = get_flashed_messages() %}
32
+ {% if messages %}
33
+ <ul>
34
+ {% for message in messages %}
35
+ <li>{{ message }}</li>
36
+ {% endfor %}
37
+ </ul>
38
+ {% endif %}
39
+ {% endwith %}
40
+ {% block content %}{% endblock %}
41
+ </body>
42
+ </html>
app/templates/index.html ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="home-div">
5
+ <img src="{{ url_for('static', filename='images/home.jpg') }}" class="home-img">
6
+ <div class="info-div">
7
+ {% if g.user %}
8
+ <h1>Welcome {{ g.user.username.capitalize() }}, </h1>
9
+ {% else %}
10
+ <h1>Sign In, Guest </h1>
11
+ {% endif %}
12
+ <h4> Explore the Test Preparation
13
+ exclusively made for you!
14
+ </h4>
15
+ <a href="{{ url_for('question', id=1)}}">Take the test</a>
16
+ </div>
17
+ </div>
18
+ {% endblock %}
app/templates/login.html ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="login-main">
5
+ <div class="login-form">
6
+ <form method="post" novalidate>
7
+ <div class="login-intro">
8
+ <h1>Login to <br> Quiz Buzz!</h1>
9
+ <p>Create any type of test, from easy <br> to complex.</p>
10
+ </div>
11
+ {{ form.hidden_tag() }}
12
+ <div class="form-para">
13
+ <svg width="30px" height="30px" viewBox="0 0 16 16" class="bi bi-person" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
14
+ <path fill-rule="evenodd" d="M10 5a2 2 0 1 1-4 0 2 2 0 0 1 4 0zM8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm6 5c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4zm-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10z"/>
15
+ </svg>
16
+ {{ form.username(placeholder="Username") }}
17
+ {% for error in form.username.errors %}
18
+ <span style="color:red;"> {{ error }} </span>
19
+ {% endfor %}
20
+ </div>
21
+ <div class="form-para">
22
+ <svg width="30px" height="30px" viewBox="0 0 16 16" class="bi bi-key" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
23
+ <path fill-rule="evenodd" d="M0 8a4 4 0 0 1 7.465-2H14a.5.5 0 0 1 .354.146l1.5 1.5a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0L13 9.207l-.646.647a.5.5 0 0 1-.708 0L11 9.207l-.646.647a.5.5 0 0 1-.708 0L9 9.207l-.646.647A.5.5 0 0 1 8 10h-.535A4 4 0 0 1 0 8zm4-3a3 3 0 1 0 2.712 4.285A.5.5 0 0 1 7.163 9h.63l.853-.854a.5.5 0 0 1 .708 0l.646.647.646-.647a.5.5 0 0 1 .708 0l.646.647.646-.647a.5.5 0 0 1 .708 0l.646.647.793-.793-1-1h-6.63a.5.5 0 0 1-.451-.285A3 3 0 0 0 4 5z"/>
24
+ <path d="M4 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
25
+ </svg>
26
+ {{ form.password(placeholder="Password") }}
27
+ {% for error in form.password.errors %}
28
+ <span style="color:red;"> {{ error }} </span>
29
+ {% endfor %}
30
+ </div>
31
+ <!-- <p>{{ form.remember_me() }} {{ form.remember_me.label }}</div> -->
32
+ <div class="form-para">
33
+ <p>Forgot Password? {{ form.submit(class="btn btn-primary") }}</p>
34
+ </div>
35
+ <div class="form-para">
36
+ <p>New User? <a href="{{ url_for('register') }}">Click to Register!</a></p>
37
+ </div>
38
+ </form>
39
+ </div>
40
+ <img src="{{ url_for('static', filename='images/boy-with-glasses.jpg') }}" class="login-img">
41
+ </div>
42
+ {% endblock %}
app/templates/question.html ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'base.html' %}
2
+
3
+
4
+ {% block content %}
5
+ <div class="ques-div">
6
+ <form method="post" novalidate>
7
+ <h2 class="qnum">Question {{q.q_id}}</h2>
8
+ <div class="dotted-spaced"></div>
9
+ <hr>
10
+ <h1 class="ques-heading">{{q.ques}}</h1>
11
+ <div class="options-div">
12
+ {{ form.options(class="list-unstyled") }}
13
+ </div>
14
+ {{ form.submit(class="btn btn-primary btn-lg sub-btn") }}
15
+ </form>
16
+ <!-- <span class="check-circle">
17
+ <i class="fas fa-check-circle"></i>
18
+ </span> -->
19
+ </div>
20
+
21
+ {% endblock %}
22
+
app/templates/register.html ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="register-main">
5
+ <img src="{{ url_for('static', filename='images/kids-studying-from-home.gif') }}" alt="kids-studying-from-home" class="register-img">
6
+ <div class="register-form">
7
+ <form action="" method="POST">
8
+ {{ form.hidden_tag() }}
9
+ <div class="register-intro">
10
+ <h1>Create your <br>Account now!</h1>
11
+ <p>Get unlimited typeforms, questions and responses. <br> Free Forever.</p>
12
+ </div>
13
+
14
+ <!-- <div class="alert alert-danger">
15
+ {% for error in form.username.errors %}
16
+ {{ error }}
17
+ {% endfor %}
18
+ {% for error in form.email.errors %}
19
+ <br>{{ error }}
20
+ {% endfor %}
21
+ {% for error in form.password.errors %}
22
+ <br>{{ error }}
23
+ {% endfor %}
24
+ {% for error in form.password2.errors %}
25
+ <br>{{ error }}
26
+ {% endfor %}
27
+ </div> -->
28
+
29
+
30
+ <div class="form-para">
31
+ <svg width="30px" height="30px" viewBox="0 0 16 16" class="bi bi-person" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
32
+ <path fill-rule="evenodd" d="M10 5a2 2 0 1 1-4 0 2 2 0 0 1 4 0zM8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm6 5c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4zm-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10z"/>
33
+ </svg>
34
+ {{ form.username(placeholder="Username") }}
35
+ {% for error in form.username.errors %}
36
+ <span style="color:red;"> {{ error }} </span>
37
+ {% endfor %}
38
+ </div>
39
+
40
+ <div class="form-para">
41
+ <svg width="30px" height="30px" viewBox="0 0 16 16" class="bi bi-envelope" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
42
+ <path fill-rule="evenodd" d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z"/>
43
+ </svg>
44
+ {{ form.email(placeholder="Email") }}
45
+ {% for error in form.email.errors %}
46
+ <span style="color:red;"> {{ error }} </span>
47
+ {% endfor %}
48
+ </div>
49
+
50
+ <div class="form-para">
51
+ <svg width="30px" height="30px" viewBox="0 0 16 16" class="bi bi-key" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
52
+ <path fill-rule="evenodd" d="M0 8a4 4 0 0 1 7.465-2H14a.5.5 0 0 1 .354.146l1.5 1.5a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0L13 9.207l-.646.647a.5.5 0 0 1-.708 0L11 9.207l-.646.647a.5.5 0 0 1-.708 0L9 9.207l-.646.647A.5.5 0 0 1 8 10h-.535A4 4 0 0 1 0 8zm4-3a3 3 0 1 0 2.712 4.285A.5.5 0 0 1 7.163 9h.63l.853-.854a.5.5 0 0 1 .708 0l.646.647.646-.647a.5.5 0 0 1 .708 0l.646.647.646-.647a.5.5 0 0 1 .708 0l.646.647.793-.793-1-1h-6.63a.5.5 0 0 1-.451-.285A3 3 0 0 0 4 5z"/>
53
+ <path d="M4 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
54
+ </svg>
55
+ {{ form.password(placeholder="Password") }}
56
+ {% for error in form.password.errors %}
57
+ <span style="color:red;"> {{ error }} </span>
58
+ {% endfor %}
59
+ </div>
60
+
61
+ <div class="form-para">
62
+ <svg width="30px" height="30px" viewBox="0 0 16 16" class="bi bi-key-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
63
+ <path fill-rule="evenodd" d="M3.5 11.5a3.5 3.5 0 1 1 3.163-5H14L15.5 8 14 9.5l-1-1-1 1-1-1-1 1-1-1-1 1H6.663a3.5 3.5 0 0 1-3.163 2zM2.5 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
64
+ </svg>
65
+ {{ form.password2(placeholder="Confirm Password") }}
66
+ {% for error in form.password2.errors %}
67
+ <span style="color:red;"> {{ error }} </span>
68
+ {% endfor %}
69
+ </div>
70
+
71
+ <div class="form-para">
72
+ <p>{{ form.submit(class="btn btn-primary") }}</p>
73
+ </div>
74
+
75
+ <div class="form-para">
76
+ <p>Already have an account? <a href="#">Login</a></p>
77
+ </div>
78
+ </form>
79
+ </div>
80
+ </div>
81
+ {% endblock %}
app/templates/score.html ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="score-main">
5
+ <div class="highest-score">
6
+ <div>Highest Score: 69 by </div> <div class="high-score-name">John</div>
7
+ </div>
8
+ <h1 class="score-head">Your Score</h1>
9
+ <div class="score-circle">
10
+ <h1>{{ g.user.marks }}</h1>
11
+ </div>
12
+ <h1 class="congrats-cls">Congratulations! <i class="fas fa-glass-cheers"></i></h1>
13
+ <div class="redirect-links">
14
+ <a href="{{ url_for('home') }}"><i class='fas fa-angle-left'></i> Home</a>
15
+ <a href="#" class="btn btn-primary disabled" >Retake Test</a>
16
+ </div>
17
+ </div>
18
+ <!-- <p>Your Final Score is {{ g.user.marks }}. Congratulations <3</p> -->
19
+ {% endblock %}
config.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ basedir = os.path.abspath(os.path.dirname(__file__))
4
+
5
+ class Config(object):
6
+ SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
7
+ SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
8
+ 'sqlite:///' + os.path.join(basedir, 'app.db')
9
+ SQLALCHEMY_TRACK_MODIFICATIONS = False
10
+ QUES_PER_PAGE = 1
main.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from app import app
2
+
3
+
4
+ # if __name__ == "__main__":
5
+ # app.run(debug=True, host='192.168.42.38')
migrations/README ADDED
@@ -0,0 +1 @@
 
 
1
+ Generic single-database configuration.
migrations/__pycache__/env.cpython-38.pyc ADDED
Binary file (2.28 kB). View file
 
migrations/alembic.ini ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # A generic, single database configuration.
2
+
3
+ [alembic]
4
+ # template used to generate migration files
5
+ # file_template = %%(rev)s_%%(slug)s
6
+
7
+ # set to 'true' to run the environment during
8
+ # the 'revision' command, regardless of autogenerate
9
+ # revision_environment = false
10
+
11
+
12
+ # Logging configuration
13
+ [loggers]
14
+ keys = root,sqlalchemy,alembic
15
+
16
+ [handlers]
17
+ keys = console
18
+
19
+ [formatters]
20
+ keys = generic
21
+
22
+ [logger_root]
23
+ level = WARN
24
+ handlers = console
25
+ qualname =
26
+
27
+ [logger_sqlalchemy]
28
+ level = WARN
29
+ handlers =
30
+ qualname = sqlalchemy.engine
31
+
32
+ [logger_alembic]
33
+ level = INFO
34
+ handlers =
35
+ qualname = alembic
36
+
37
+ [handler_console]
38
+ class = StreamHandler
39
+ args = (sys.stderr,)
40
+ level = NOTSET
41
+ formatter = generic
42
+
43
+ [formatter_generic]
44
+ format = %(levelname)-5.5s [%(name)s] %(message)s
45
+ datefmt = %H:%M:%S
migrations/env.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import with_statement
2
+
3
+ import logging
4
+ from logging.config import fileConfig
5
+
6
+ from sqlalchemy import engine_from_config
7
+ from sqlalchemy import pool
8
+
9
+ from alembic import context
10
+
11
+ # this is the Alembic Config object, which provides
12
+ # access to the values within the .ini file in use.
13
+ config = context.config
14
+
15
+ # Interpret the config file for Python logging.
16
+ # This line sets up loggers basically.
17
+ fileConfig(config.config_file_name)
18
+ logger = logging.getLogger('alembic.env')
19
+
20
+ # add your model's MetaData object here
21
+ # for 'autogenerate' support
22
+ # from myapp import mymodel
23
+ # target_metadata = mymodel.Base.metadata
24
+ from flask import current_app
25
+ config.set_main_option(
26
+ 'sqlalchemy.url',
27
+ str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%'))
28
+ target_metadata = current_app.extensions['migrate'].db.metadata
29
+
30
+ # other values from the config, defined by the needs of env.py,
31
+ # can be acquired:
32
+ # my_important_option = config.get_main_option("my_important_option")
33
+ # ... etc.
34
+
35
+
36
+ def run_migrations_offline():
37
+ """Run migrations in 'offline' mode.
38
+
39
+ This configures the context with just a URL
40
+ and not an Engine, though an Engine is acceptable
41
+ here as well. By skipping the Engine creation
42
+ we don't even need a DBAPI to be available.
43
+
44
+ Calls to context.execute() here emit the given string to the
45
+ script output.
46
+
47
+ """
48
+ url = config.get_main_option("sqlalchemy.url")
49
+ context.configure(
50
+ url=url, target_metadata=target_metadata, literal_binds=True
51
+ )
52
+
53
+ with context.begin_transaction():
54
+ context.run_migrations()
55
+
56
+
57
+ def run_migrations_online():
58
+ """Run migrations in 'online' mode.
59
+
60
+ In this scenario we need to create an Engine
61
+ and associate a connection with the context.
62
+
63
+ """
64
+
65
+ # this callback is used to prevent an auto-migration from being generated
66
+ # when there are no changes to the schema
67
+ # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
68
+ def process_revision_directives(context, revision, directives):
69
+ if getattr(config.cmd_opts, 'autogenerate', False):
70
+ script = directives[0]
71
+ if script.upgrade_ops.is_empty():
72
+ directives[:] = []
73
+ logger.info('No changes in schema detected.')
74
+
75
+ connectable = engine_from_config(
76
+ config.get_section(config.config_ini_section),
77
+ prefix='sqlalchemy.',
78
+ poolclass=pool.NullPool,
79
+ )
80
+
81
+ with connectable.connect() as connection:
82
+ context.configure(
83
+ connection=connection,
84
+ target_metadata=target_metadata,
85
+ process_revision_directives=process_revision_directives,
86
+ **current_app.extensions['migrate'].configure_args
87
+ )
88
+
89
+ with context.begin_transaction():
90
+ context.run_migrations()
91
+
92
+
93
+ if context.is_offline_mode():
94
+ run_migrations_offline()
95
+ else:
96
+ run_migrations_online()
migrations/script.py.mako ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """${message}
2
+
3
+ Revision ID: ${up_revision}
4
+ Revises: ${down_revision | comma,n}
5
+ Create Date: ${create_date}
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+ ${imports if imports else ""}
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = ${repr(up_revision)}
14
+ down_revision = ${repr(down_revision)}
15
+ branch_labels = ${repr(branch_labels)}
16
+ depends_on = ${repr(depends_on)}
17
+
18
+
19
+ def upgrade():
20
+ ${upgrades if upgrades else "pass"}
21
+
22
+
23
+ def downgrade():
24
+ ${downgrades if downgrades else "pass"}
migrations/versions/4f3f4537bb29_users_table.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """users table
2
+
3
+ Revision ID: 4f3f4537bb29
4
+ Revises: a635661f4a03
5
+ Create Date: 2020-09-22 13:41:27.540099
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '4f3f4537bb29'
14
+ down_revision = 'a635661f4a03'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ op.create_table('user',
22
+ sa.Column('id', sa.Integer(), nullable=False),
23
+ sa.Column('username', sa.String(length=64), nullable=True),
24
+ sa.Column('email', sa.String(length=120), nullable=True),
25
+ sa.Column('password_hash', sa.String(length=128), nullable=True),
26
+ sa.PrimaryKeyConstraint('id')
27
+ )
28
+ op.create_index(op.f('ix_user_email'), 'user', ['email'], unique=True)
29
+ op.create_index(op.f('ix_user_username'), 'user', ['username'], unique=True)
30
+ # ### end Alembic commands ###
31
+
32
+
33
+ def downgrade():
34
+ # ### commands auto generated by Alembic - please adjust! ###
35
+ op.drop_index(op.f('ix_user_username'), table_name='user')
36
+ op.drop_index(op.f('ix_user_email'), table_name='user')
37
+ op.drop_table('user')
38
+ # ### end Alembic commands ###
migrations/versions/59069a416ef2_question_table.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """question Table
2
+
3
+ Revision ID: 59069a416ef2
4
+ Revises: 9c77048e7767
5
+ Create Date: 2020-09-22 19:15:22.752938
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '59069a416ef2'
14
+ down_revision = '9c77048e7767'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ op.create_table('questions',
22
+ sa.Column('q_id', sa.Integer(), nullable=False),
23
+ sa.Column('ques', sa.String(length=350), nullable=True),
24
+ sa.Column('a', sa.String(length=100), nullable=True),
25
+ sa.Column('b', sa.String(length=100), nullable=True),
26
+ sa.Column('c', sa.String(length=100), nullable=True),
27
+ sa.Column('d', sa.String(length=100), nullable=True),
28
+ sa.Column('ans', sa.String(length=100), nullable=True),
29
+ sa.Column('marks', sa.Integer(), nullable=True),
30
+ sa.PrimaryKeyConstraint('q_id'),
31
+ sa.UniqueConstraint('ques')
32
+ )
33
+ op.create_index(op.f('ix_questions_marks'), 'questions', ['marks'], unique=False)
34
+ # ### end Alembic commands ###
35
+
36
+
37
+ def downgrade():
38
+ # ### commands auto generated by Alembic - please adjust! ###
39
+ op.drop_index(op.f('ix_questions_marks'), table_name='questions')
40
+ op.drop_table('questions')
41
+ # ### end Alembic commands ###
migrations/versions/9c77048e7767_questions_table.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """questions table
2
+
3
+ Revision ID: 9c77048e7767
4
+ Revises: 4f3f4537bb29
5
+ Create Date: 2020-09-22 18:51:37.951537
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '9c77048e7767'
14
+ down_revision = '4f3f4537bb29'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ op.create_table('questions',
22
+ sa.Column('q_id', sa.Integer(), nullable=False),
23
+ sa.Column('ques', sa.String(length=350), nullable=True),
24
+ sa.Column('a', sa.String(length=100), nullable=True),
25
+ sa.Column('b', sa.String(length=100), nullable=True),
26
+ sa.Column('c', sa.String(length=100), nullable=True),
27
+ sa.Column('d', sa.String(length=100), nullable=True),
28
+ sa.Column('ans', sa.String(length=1), nullable=True),
29
+ sa.Column('marks', sa.Integer(), nullable=True),
30
+ sa.PrimaryKeyConstraint('q_id'),
31
+ sa.UniqueConstraint('ques')
32
+ )
33
+ op.create_index(op.f('ix_questions_ans'), 'questions', ['ans'], unique=False)
34
+ op.create_index(op.f('ix_questions_marks'), 'questions', ['marks'], unique=False)
35
+ # ### end Alembic commands ###
36
+
37
+
38
+ def downgrade():
39
+ # ### commands auto generated by Alembic - please adjust! ###
40
+ op.drop_index(op.f('ix_questions_marks'), table_name='questions')
41
+ op.drop_index(op.f('ix_questions_ans'), table_name='questions')
42
+ op.drop_table('questions')
43
+ # ### end Alembic commands ###
migrations/versions/__pycache__/4f3f4537bb29_users_table.cpython-38.pyc ADDED
Binary file (1.16 kB). View file
 
migrations/versions/__pycache__/59069a416ef2_question_table.cpython-38.pyc ADDED
Binary file (1.21 kB). View file
 
migrations/versions/__pycache__/9c77048e7767_questions_table.cpython-38.pyc ADDED
Binary file (1.29 kB). View file
 
migrations/versions/__pycache__/a635661f4a03_users_table.cpython-38.pyc ADDED
Binary file (1.13 kB). View file
 
migrations/versions/__pycache__/e96865e4fa62_users_added_marks.cpython-38.pyc ADDED
Binary file (1.28 kB). View file
 
migrations/versions/a635661f4a03_users_table.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """users table
2
+
3
+ Revision ID: a635661f4a03
4
+ Revises:
5
+ Create Date: 2020-09-21 23:00:27.622934
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = 'a635661f4a03'
14
+ down_revision = None
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ op.create_table('user',
22
+ sa.Column('id', sa.Integer(), nullable=False),
23
+ sa.Column('username', sa.String(length=64), nullable=True),
24
+ sa.Column('email', sa.String(length=120), nullable=True),
25
+ sa.Column('password_hash', sa.String(length=128), nullable=True),
26
+ sa.PrimaryKeyConstraint('id')
27
+ )
28
+ op.create_index(op.f('ix_user_email'), 'user', ['email'], unique=True)
29
+ op.create_index(op.f('ix_user_username'), 'user', ['username'], unique=True)
30
+ # ### end Alembic commands ###
31
+
32
+
33
+ def downgrade():
34
+ # ### commands auto generated by Alembic - please adjust! ###
35
+ op.drop_index(op.f('ix_user_username'), table_name='user')
36
+ op.drop_index(op.f('ix_user_email'), table_name='user')
37
+ op.drop_table('user')
38
+ # ### end Alembic commands ###
migrations/versions/e96865e4fa62_users_added_marks.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """users added marks
2
+
3
+ Revision ID: e96865e4fa62
4
+ Revises: 59069a416ef2
5
+ Create Date: 2020-09-23 14:29:28.764869
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = 'e96865e4fa62'
14
+ down_revision = '59069a416ef2'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ op.create_table('questions',
22
+ sa.Column('q_id', sa.Integer(), nullable=False),
23
+ sa.Column('ques', sa.String(length=350), nullable=True),
24
+ sa.Column('a', sa.String(length=100), nullable=True),
25
+ sa.Column('b', sa.String(length=100), nullable=True),
26
+ sa.Column('c', sa.String(length=100), nullable=True),
27
+ sa.Column('d', sa.String(length=100), nullable=True),
28
+ sa.Column('ans', sa.String(length=100), nullable=True),
29
+ sa.PrimaryKeyConstraint('q_id'),
30
+ sa.UniqueConstraint('ques')
31
+ )
32
+ op.add_column('user', sa.Column('marks', sa.Integer(), nullable=True))
33
+ op.create_index(op.f('ix_user_marks'), 'user', ['marks'], unique=False)
34
+ # ### end Alembic commands ###
35
+
36
+
37
+ def downgrade():
38
+ # ### commands auto generated by Alembic - please adjust! ###
39
+ op.drop_index(op.f('ix_user_marks'), table_name='user')
40
+ op.drop_column('user', 'marks')
41
+ op.drop_table('questions')
42
+ # ### end Alembic commands ###