Skip to content

Commit 2bc2de9

Browse files
committed
first commit
0 parents  commit 2bc2de9

13 files changed

+384
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.vscode
2+
website/__pycache__
3+
website/database.db

README.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Flask Web App Tutorial
2+
3+
## Setup & Installtion
4+
5+
Make sure you have the latest version of pythin installed.
6+
7+
```bash
8+
git clone <repo-url>
9+
```
10+
11+
```bash
12+
pip install -r requirements.txt
13+
```
14+
15+
## Running The App
16+
17+
```bash
18+
python main.py
19+
```
20+
21+
## Viewing The App
22+
23+
Go to `http://127.0.0.1:5000`

main.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from website import create_app
2+
3+
app = create_app()
4+
5+
if __name__ == '__main__':
6+
app.run(debug=True)

requirements.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
flask
2+
Flask-SQLAlchemy
3+
flask-login

website/__init__.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from flask import Flask
2+
from flask_sqlalchemy import SQLAlchemy
3+
from os import path
4+
from flask_login import LoginManager
5+
6+
db = SQLAlchemy()
7+
DB_NAME = "database.db"
8+
9+
10+
def create_app():
11+
app = Flask(__name__)
12+
app.config['SECRET_KEY'] = 'hjshjhdjah kjshkjdhjs'
13+
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
14+
db.init_app(app)
15+
16+
from .views import views
17+
from .auth import auth
18+
19+
app.register_blueprint(views, url_prefix='/')
20+
app.register_blueprint(auth, url_prefix='/')
21+
22+
from .models import User, Note
23+
24+
create_database(app)
25+
26+
login_manager = LoginManager()
27+
login_manager.login_view = 'auth.login'
28+
login_manager.init_app(app)
29+
30+
@login_manager.user_loader
31+
def load_user(id):
32+
return User.query.get(int(id))
33+
34+
return app
35+
36+
37+
def create_database(app):
38+
if not path.exists('website/' + DB_NAME):
39+
db.create_all(app=app)
40+
print('Created Database!')

website/auth.py

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from flask import Blueprint, render_template, request, flash, redirect, url_for
2+
from .models import User
3+
from werkzeug.security import generate_password_hash, check_password_hash
4+
from . import db
5+
from flask_login import login_user, login_required, logout_user, current_user
6+
7+
8+
auth = Blueprint('auth', __name__)
9+
10+
11+
@auth.route('/login', methods=['GET', 'POST'])
12+
def login():
13+
if request.method == 'POST':
14+
email = request.form.get('email')
15+
password = request.form.get('password')
16+
17+
user = User.query.filter_by(email=email).first()
18+
if user:
19+
if check_password_hash(user.password, password):
20+
flash('Logged in successfully!', category='success')
21+
login_user(user, remember=True)
22+
return redirect(url_for('views.home'))
23+
else:
24+
flash('Incorrect password, try again.', category='error')
25+
else:
26+
flash('Email does not exist.', category='error')
27+
28+
return render_template("login.html", user=current_user)
29+
30+
31+
@auth.route('/logout')
32+
@login_required
33+
def logout():
34+
logout_user()
35+
return redirect(url_for('auth.login'))
36+
37+
38+
@auth.route('/sign-up', methods=['GET', 'POST'])
39+
def sign_up():
40+
if request.method == 'POST':
41+
email = request.form.get('email')
42+
first_name = request.form.get('firstName')
43+
password1 = request.form.get('password1')
44+
password2 = request.form.get('password2')
45+
46+
user = User.query.filter_by(email=email).first()
47+
if user:
48+
flash('Email already exists.', category='error')
49+
elif len(email) < 4:
50+
flash('Email must be greater than 3 characters.', category='error')
51+
elif len(first_name) < 2:
52+
flash('First name must be greater than 1 character.', category='error')
53+
elif password1 != password2:
54+
flash('Passwords don\'t match.', category='error')
55+
elif len(password1) < 7:
56+
flash('Password must be at least 7 characters.', category='error')
57+
else:
58+
new_user = User(email=email, first_name=first_name, password=generate_password_hash(
59+
password1, method='sha256'))
60+
db.session.add(new_user)
61+
db.session.commit()
62+
login_user(user, remember=True)
63+
flash('Account created!', category='success')
64+
return redirect(url_for('views.home'))
65+
66+
return render_template("sign_up.html", user=current_user)

website/models.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from . import db
2+
from flask_login import UserMixin
3+
from sqlalchemy.sql import func
4+
5+
6+
class Note(db.Model):
7+
id = db.Column(db.Integer, primary_key=True)
8+
data = db.Column(db.String(10000))
9+
date = db.Column(db.DateTime(timezone=True), default=func.now())
10+
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
11+
12+
13+
class User(db.Model, UserMixin):
14+
id = db.Column(db.Integer, primary_key=True)
15+
email = db.Column(db.String(150), unique=True)
16+
password = db.Column(db.String(150))
17+
first_name = db.Column(db.String(150))
18+
notes = db.relationship('Note')

website/static/index.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
function deleteNote(noteId) {
2+
fetch("/delete-note", {
3+
method: "POST",
4+
body: JSON.stringify({ noteId: noteId }),
5+
}).then((_res) => {
6+
window.location.href = "/";
7+
});
8+
}

website/templates/base.html

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<link
7+
rel="stylesheet"
8+
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
9+
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
10+
crossorigin="anonymous"
11+
/>
12+
<link
13+
rel="stylesheet"
14+
href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
15+
crossorigin="anonymous"
16+
/>
17+
18+
<title>{% block title %}Home{% endblock %}</title>
19+
</head>
20+
<body>
21+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
22+
<button
23+
class="navbar-toggler"
24+
type="button"
25+
data-toggle="collapse"
26+
data-target="#navbar"
27+
>
28+
<span class="navbar-toggler-icon"></span>
29+
</button>
30+
<div class="collapse navbar-collapse" id="navbar">
31+
<div class="navbar-nav">
32+
{% if user.is_authenticated %}
33+
<a class="nav-item nav-link" id="home" href="/">Home</a>
34+
<a class="nav-item nav-link" id="logout" href="/logout">Logout</a>
35+
{% else %}
36+
<a class="nav-item nav-link" id="login" href="/login">Login</a>
37+
<a class="nav-item nav-link" id="signUp" href="/sign-up">Sign Up</a>
38+
{% endif %}
39+
</div>
40+
</div>
41+
</nav>
42+
43+
{% with messages = get_flashed_messages(with_categories=true) %} {% if
44+
messages %} {% for category, message in messages %} {% if category ==
45+
'error' %}
46+
<div class="alert alert-danger alter-dismissable fade show" role="alert">
47+
{{ message }}
48+
<button type="button" class="close" data-dismiss="alert">
49+
<span aria-hidden="true">&times;</span>
50+
</button>
51+
</div>
52+
{% else %}
53+
<div class="alert alert-success alter-dismissable fade show" role="alert">
54+
{{ message }}
55+
<button type="button" class="close" data-dismiss="alert">
56+
<span aria-hidden="true">&times;</span>
57+
</button>
58+
</div>
59+
{% endif %} {% endfor %} {% endif %} {% endwith %}
60+
61+
<div class="container">{% block content %} {% endblock %}</div>
62+
<script
63+
src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
64+
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
65+
crossorigin="anonymous"
66+
></script>
67+
<script
68+
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
69+
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
70+
crossorigin="anonymous"
71+
></script>
72+
<script
73+
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
74+
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
75+
crossorigin="anonymous"
76+
></script>
77+
78+
<script
79+
type="text/javascript"
80+
src="{{ url_for('static', filename='index.js') }}"
81+
></script>
82+
</body>
83+
</html>

website/templates/home.html

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{% extends "base.html" %} {% block title %}Home{% endblock %} {% block content
2+
%}
3+
<h1 align="center">Notes</h1>
4+
<ul class="list-group list-group-flush" id="notes">
5+
{% for note in user.notes %}
6+
<li class="list-group-item">
7+
{{ note.data }}
8+
<button type="button" class="close" onClick="deleteNote({{ note.id }})">
9+
<span aria-hidden="true">&times;</span>
10+
</button>
11+
</li>
12+
{% endfor %}
13+
</ul>
14+
<form method="POST">
15+
<textarea name="note" id="note" class="form-control"></textarea>
16+
<br />
17+
<div align="center">
18+
<button type="submit" class="btn btn-primary">Add Note</button>
19+
</div>
20+
</form>
21+
{% endblock %}

website/templates/login.html

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{% extends "base.html" %} {% block title %}Login{% endblock %} {% block content
2+
%}
3+
<form method="POST">
4+
<h3 align="center">Login</h3>
5+
<div class="form-group">
6+
<label for="email">Email Address</label>
7+
<input
8+
type="email"
9+
class="form-control"
10+
id="email"
11+
name="email"
12+
placeholder="Enter email"
13+
/>
14+
</div>
15+
<div class="form-group">
16+
<label for="password">Password</label>
17+
<input
18+
type="password"
19+
class="form-control"
20+
id="password"
21+
name="password"
22+
placeholder="Enter password"
23+
/>
24+
</div>
25+
<br />
26+
<button type="submit" class="btn btn-primary">Login</button>
27+
</form>
28+
{% endblock %}

website/templates/sign_up.html

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{% extends "base.html" %} {% block title %}Sign Up{% endblock %} {% block
2+
content %}
3+
<form method="POST">
4+
<h3 align="center">Sign Up</h3>
5+
<div class="form-group">
6+
<label for="email">Email Address</label>
7+
<input
8+
type="email"
9+
class="form-control"
10+
id="email"
11+
name="email"
12+
placeholder="Enter email"
13+
/>
14+
</div>
15+
<div class="form-group">
16+
<label for="firstName">First Name</label>
17+
<input
18+
type="text"
19+
class="form-control"
20+
id="firstName"
21+
name="firstName"
22+
placeholder="Enter first name"
23+
/>
24+
</div>
25+
<div class="form-group">
26+
<label for="password1">Password</label>
27+
<input
28+
type="password"
29+
class="form-control"
30+
id="password1"
31+
name="password1"
32+
placeholder="Enter password"
33+
/>
34+
</div>
35+
<div class="form-group">
36+
<label for="password2">Password (Confirm)</label>
37+
<input
38+
type="password"
39+
class="form-control"
40+
id="password2"
41+
name="password2"
42+
placeholder="Confirm password"
43+
/>
44+
</div>
45+
<br />
46+
<button type="submit" class="btn btn-primary">Submit</button>
47+
</form>
48+
{% endblock %}

website/views.py

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from flask import Blueprint, render_template, request, flash, jsonify
2+
from flask_login import login_required, current_user
3+
from .models import Note
4+
from . import db
5+
import json
6+
7+
views = Blueprint('views', __name__)
8+
9+
10+
@views.route('/', methods=['GET', 'POST'])
11+
@login_required
12+
def home():
13+
if request.method == 'POST':
14+
note = request.form.get('note')
15+
16+
if len(note) < 1:
17+
flash('Note is too short!', category='error')
18+
else:
19+
new_note = Note(data=note, user_id=current_user.id)
20+
db.session.add(new_note)
21+
db.session.commit()
22+
flash('Note added!', category='success')
23+
24+
return render_template("home.html", user=current_user)
25+
26+
27+
@views.route('/delete-note', methods=['POST'])
28+
def delete_note():
29+
note = json.loads(request.data)
30+
noteId = note['noteId']
31+
note = Note.query.get(noteId)
32+
if note:
33+
if note.user_id == current_user.id:
34+
db.session.delete(note)
35+
db.session.commit()
36+
37+
return jsonify({})

0 commit comments

Comments
 (0)