|
| 1 | +from flask import Flask, render_template, redirect, url_for, flash, abort |
| 2 | +from flask_bootstrap import Bootstrap |
| 3 | +from flask_ckeditor import CKEditor |
| 4 | +from datetime import date |
| 5 | +from functools import wraps |
| 6 | +from werkzeug.security import generate_password_hash, check_password_hash |
| 7 | +from flask_sqlalchemy import SQLAlchemy |
| 8 | +from sqlalchemy.orm import relationship |
| 9 | +from flask_login import UserMixin, login_user, LoginManager, login_required, current_user, logout_user |
| 10 | +from forms import LoginForm, RegisterForm, CreatePostForm, CommentForm |
| 11 | +from flask_gravatar import Gravatar |
| 12 | + |
| 13 | +app = Flask(__name__) |
| 14 | +app.config['SECRET_KEY'] = '8BYkEfBA6O6donzWlSihBXox7C0sKR6b' |
| 15 | +ckeditor = CKEditor(app) |
| 16 | +Bootstrap(app) |
| 17 | +gravatar = Gravatar(app, size=100, rating='g', default='retro', force_default=False, force_lower=False, use_ssl=False, base_url=None) |
| 18 | + |
| 19 | +##CONNECT TO DB |
| 20 | +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db' |
| 21 | +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
| 22 | +db = SQLAlchemy(app) |
| 23 | +login_manager = LoginManager() |
| 24 | +login_manager.init_app(app) |
| 25 | + |
| 26 | + |
| 27 | +@login_manager.user_loader |
| 28 | +def load_user(user_id): |
| 29 | + return User.query.get(int(user_id)) |
| 30 | + |
| 31 | + |
| 32 | +##CONFIGURE TABLE |
| 33 | +class User(UserMixin, db.Model): |
| 34 | + __tablename__ = "users" |
| 35 | + id = db.Column(db.Integer, primary_key=True) |
| 36 | + email = db.Column(db.String(100), unique=True) |
| 37 | + password = db.Column(db.String(100)) |
| 38 | + name = db.Column(db.String(100)) |
| 39 | + posts = relationship("BlogPost", back_populates="author") |
| 40 | + comments = relationship("Comment", back_populates="comment_author") |
| 41 | + |
| 42 | + |
| 43 | +class BlogPost(db.Model): |
| 44 | + __tablename__ = "blog_posts" |
| 45 | + id = db.Column(db.Integer, primary_key=True) |
| 46 | + author_id = db.Column(db.Integer, db.ForeignKey("users.id")) |
| 47 | + author = relationship("User", back_populates="posts") |
| 48 | + title = db.Column(db.String(250), unique=True, nullable=False) |
| 49 | + subtitle = db.Column(db.String(250), nullable=False) |
| 50 | + date = db.Column(db.String(250), nullable=False) |
| 51 | + body = db.Column(db.Text, nullable=False) |
| 52 | + img_url = db.Column(db.String(250), nullable=False) |
| 53 | + comments = relationship("Comment", back_populates="parent_post") |
| 54 | + |
| 55 | + |
| 56 | +class Comment(db.Model): |
| 57 | + __tablename__ = "comments" |
| 58 | + id = db.Column(db.Integer, primary_key=True) |
| 59 | + post_id = db.Column(db.Integer, db.ForeignKey("blog_posts.id")) |
| 60 | + author_id = db.Column(db.Integer, db.ForeignKey("users.id")) |
| 61 | + parent_post = relationship("BlogPost", back_populates="comments") |
| 62 | + comment_author = relationship("User", back_populates="comments") |
| 63 | + text = db.Column(db.Text, nullable=False) |
| 64 | +db.create_all() |
| 65 | + |
| 66 | + |
| 67 | +def admin_only(f): |
| 68 | + @wraps(f) |
| 69 | + def decorated_function(*args, **kwargs): |
| 70 | + if current_user.id != 1: |
| 71 | + return abort(403) |
| 72 | + return f(*args, **kwargs) |
| 73 | + return decorated_function |
| 74 | + |
| 75 | + |
| 76 | +@app.route('/') |
| 77 | +def get_all_posts(): |
| 78 | + posts = BlogPost.query.all() |
| 79 | + return render_template("index.html", all_posts=posts, current_user=current_user) |
| 80 | + |
| 81 | + |
| 82 | +@app.route('/register', methods=["GET", "POST"]) |
| 83 | +def register(): |
| 84 | + form = RegisterForm() |
| 85 | + if form.validate_on_submit(): |
| 86 | + |
| 87 | + if User.query.filter_by(email=form.email.data).first(): |
| 88 | + print(User.query.filter_by(email=form.email.data).first()) |
| 89 | + #User already exists |
| 90 | + flash("You've already signed up with that email, log in instead!") |
| 91 | + return redirect(url_for('login')) |
| 92 | + |
| 93 | + hash_and_salted_password = generate_password_hash( |
| 94 | + form.password.data, |
| 95 | + method='pbkdf2:sha256', |
| 96 | + salt_length=8 |
| 97 | + ) |
| 98 | + new_user = User( |
| 99 | + email=form.email.data, |
| 100 | + name=form.name.data, |
| 101 | + password=hash_and_salted_password, |
| 102 | + ) |
| 103 | + db.session.add(new_user) |
| 104 | + db.session.commit() |
| 105 | + login_user(new_user) |
| 106 | + return redirect(url_for("get_all_posts")) |
| 107 | + |
| 108 | + return render_template("register.html", form=form, current_user=current_user) |
| 109 | + |
| 110 | + |
| 111 | +@app.route('/login', methods=["GET", "POST"]) |
| 112 | +def login(): |
| 113 | + form = LoginForm() |
| 114 | + if form.validate_on_submit(): |
| 115 | + email = form.email.data |
| 116 | + password = form.password.data |
| 117 | + |
| 118 | + user = User.query.filter_by(email=email).first() |
| 119 | + # Email doesn't exist or password incorrect. |
| 120 | + if not user: |
| 121 | + flash("That email does not exist, please try again.") |
| 122 | + return redirect(url_for('login')) |
| 123 | + elif not check_password_hash(user.password, password): |
| 124 | + flash('Password incorrect, please try again.') |
| 125 | + return redirect(url_for('login')) |
| 126 | + else: |
| 127 | + login_user(user) |
| 128 | + return redirect(url_for('get_all_posts')) |
| 129 | + return render_template("login.html", form=form, current_user=current_user) |
| 130 | + |
| 131 | + |
| 132 | +@app.route('/logout') |
| 133 | +def logout(): |
| 134 | + logout_user() |
| 135 | + return redirect(url_for('get_all_posts')) |
| 136 | + |
| 137 | + |
| 138 | +@app.route("/post/<int:post_id>", methods=["GET", "POST"]) |
| 139 | +def show_post(post_id): |
| 140 | + form = CommentForm() |
| 141 | + requested_post = BlogPost.query.get(post_id) |
| 142 | + |
| 143 | + if form.validate_on_submit(): |
| 144 | + if not current_user.is_authenticated: |
| 145 | + flash("You need to login or register to comment.") |
| 146 | + return redirect(url_for("login")) |
| 147 | + |
| 148 | + new_comment = Comment( |
| 149 | + text=form.comment_text.data, |
| 150 | + comment_author=current_user, |
| 151 | + parent_post=requested_post |
| 152 | + ) |
| 153 | + db.session.add(new_comment) |
| 154 | + db.session.commit() |
| 155 | + |
| 156 | + return render_template("post.html", post=requested_post, form=form, current_user=current_user) |
| 157 | + |
| 158 | + |
| 159 | +@app.route("/about") |
| 160 | +def about(): |
| 161 | + return render_template("about.html", current_user=current_user) |
| 162 | + |
| 163 | + |
| 164 | +@app.route("/contact") |
| 165 | +def contact(): |
| 166 | + return render_template("contact.html", current_user=current_user) |
| 167 | + |
| 168 | + |
| 169 | +@app.route("/new-post", methods=["GET", "POST"]) |
| 170 | +@admin_only |
| 171 | +def add_new_post(): |
| 172 | + form = CreatePostForm() |
| 173 | + if form.validate_on_submit(): |
| 174 | + new_post = BlogPost( |
| 175 | + title=form.title.data, |
| 176 | + subtitle=form.subtitle.data, |
| 177 | + body=form.body.data, |
| 178 | + img_url=form.img_url.data, |
| 179 | + author=current_user, |
| 180 | + date=date.today().strftime("%B %d, %Y") |
| 181 | + ) |
| 182 | + db.session.add(new_post) |
| 183 | + db.session.commit() |
| 184 | + return redirect(url_for("get_all_posts")) |
| 185 | + |
| 186 | + return render_template("make-post.html", form=form, current_user=current_user) |
| 187 | + |
| 188 | + |
| 189 | + |
| 190 | + |
| 191 | +@app.route("/edit-post/<int:post_id>", methods=["GET", "POST"]) |
| 192 | +@admin_only |
| 193 | +def edit_post(post_id): |
| 194 | + post = BlogPost.query.get(post_id) |
| 195 | + edit_form = CreatePostForm( |
| 196 | + title=post.title, |
| 197 | + subtitle=post.subtitle, |
| 198 | + img_url=post.img_url, |
| 199 | + author=current_user, |
| 200 | + body=post.body |
| 201 | + ) |
| 202 | + if edit_form.validate_on_submit(): |
| 203 | + post.title = edit_form.title.data |
| 204 | + post.subtitle = edit_form.subtitle.data |
| 205 | + post.img_url = edit_form.img_url.data |
| 206 | + post.body = edit_form.body.data |
| 207 | + db.session.commit() |
| 208 | + return redirect(url_for("show_post", post_id=post.id)) |
| 209 | + |
| 210 | + return render_template("make-post.html", form=edit_form, is_edit=True, current_user=current_user) |
| 211 | + |
| 212 | + |
| 213 | +@app.route("/delete/<int:post_id>") |
| 214 | +@admin_only |
| 215 | +def delete_post(post_id): |
| 216 | + post_to_delete = BlogPost.query.get(post_id) |
| 217 | + db.session.delete(post_to_delete) |
| 218 | + db.session.commit() |
| 219 | + return redirect(url_for('get_all_posts')) |
| 220 | + |
| 221 | + |
| 222 | +if __name__ == "__main__": |
| 223 | + app.run(host='0.0.0.0', port=5000) |
0 commit comments