Spaces:
Sleeping
Sleeping
Add application file
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- Procfile +1 -0
- README.md +1 -5
- __pycache__/config.cpython-311.pyc +0 -0
- __pycache__/config.cpython-38.pyc +0 -0
- __pycache__/main.cpython-37.pyc +0 -0
- app.db +0 -0
- app/__init__.py +11 -0
- app/__pycache__/__init__.cpython-311.pyc +0 -0
- app/__pycache__/__init__.cpython-37.pyc +0 -0
- app/__pycache__/__init__.cpython-38.pyc +0 -0
- app/__pycache__/forms.cpython-311.pyc +0 -0
- app/__pycache__/forms.cpython-37.pyc +0 -0
- app/__pycache__/forms.cpython-38.pyc +0 -0
- app/__pycache__/models.cpython-311.pyc +0 -0
- app/__pycache__/models.cpython-38.pyc +0 -0
- app/__pycache__/routes.cpython-311.pyc +0 -0
- app/__pycache__/routes.cpython-37.pyc +0 -0
- app/__pycache__/routes.cpython-38.pyc +0 -0
- app/forms.py +34 -0
- app/models.py +30 -0
- app/routes.py +87 -0
- app/static/css/mob-styles.css +178 -0
- app/static/css/styles.css +358 -0
- app/static/images/boy-with-glasses.jpg +0 -0
- app/static/images/check-circle-solid.svg +1 -0
- app/static/images/home.jpg +0 -0
- app/static/images/kids-studying-from-home.gif +0 -0
- app/templates/base.html +42 -0
- app/templates/index.html +18 -0
- app/templates/login.html +42 -0
- app/templates/question.html +22 -0
- app/templates/register.html +81 -0
- app/templates/score.html +19 -0
- config.py +10 -0
- main.py +5 -0
- migrations/README +1 -0
- migrations/__pycache__/env.cpython-38.pyc +0 -0
- migrations/alembic.ini +45 -0
- migrations/env.py +96 -0
- migrations/script.py.mako +24 -0
- migrations/versions/4f3f4537bb29_users_table.py +38 -0
- migrations/versions/59069a416ef2_question_table.py +41 -0
- migrations/versions/9c77048e7767_questions_table.py +43 -0
- migrations/versions/__pycache__/4f3f4537bb29_users_table.cpython-38.pyc +0 -0
- migrations/versions/__pycache__/59069a416ef2_question_table.cpython-38.pyc +0 -0
- migrations/versions/__pycache__/9c77048e7767_questions_table.cpython-38.pyc +0 -0
- migrations/versions/__pycache__/a635661f4a03_users_table.cpython-38.pyc +0 -0
- migrations/versions/__pycache__/e96865e4fa62_users_added_marks.cpython-38.pyc +0 -0
- migrations/versions/a635661f4a03_users_table.py +38 -0
- 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 ###
|