├── Procfile ├── __pycache__ └── hello.cpython-39.pyc ├── app.py ├── create_db.py ├── migrations ├── README ├── alembic.ini ├── env.py ├── script.py.mako └── versions │ ├── 5f8bac49757f_about_author_added.py │ ├── a7bc9bb228d8_added_profile_pic.py │ ├── e47c843a6860_remove_author.py │ └── f26432df1173_add_foreign_key.py ├── requirements.txt ├── static ├── css │ └── style.css ├── images │ ├── 4b927b0b-7f8f-11ec-8fe3-34e894657787_my_profile.png │ ├── 54d448aa-8518-11ec-a2a5-34e894657787_planking.png │ ├── 5cfef60e-8518-11ec-b98c-34e894657787_my_profile.png │ ├── 7978f08c-8a91-11ec-a01e-34e894657787_my_profile.png │ ├── NorthPeak.png │ ├── dbbaecd1-8517-11ec-a660-34e894657787_ │ ├── default_profile_pic.png │ ├── e58ac37a-7f8e-11ec-86c2-34e894657787_my_profile.png │ ├── efd91395-7f8e-11ec-821c-34e894657787_pool.jpg │ └── f095ba31-8517-11ec-ae00-34e894657787_my_profile.png └── js │ └── myfile.js ├── templates ├── 404.html ├── 500.html ├── add_post.html ├── add_user.html ├── admin.html ├── base.html ├── dashboard.html ├── edit_post.html ├── index.html ├── login.html ├── name.html ├── navbar.html ├── post.html ├── posts.html ├── search.html ├── test_pw.html ├── update.html └── user.html ├── users.db └── webforms.py /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn app:app 2 | -------------------------------------------------------------------------------- /__pycache__/hello.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/__pycache__/hello.cpython-39.pyc -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, flash, request, redirect, url_for 2 | from datetime import datetime 3 | from flask_sqlalchemy import SQLAlchemy 4 | from flask_migrate import Migrate 5 | from werkzeug.security import generate_password_hash, check_password_hash 6 | from datetime import date 7 | from webforms import LoginForm, PostForm, UserForm, PasswordForm, NamerForm, SearchForm 8 | from flask_login import UserMixin, login_user, LoginManager, login_required, logout_user, current_user 9 | from webforms import LoginForm, PostForm, UserForm, PasswordForm, NamerForm 10 | from flask_ckeditor import CKEditor 11 | from werkzeug.utils import secure_filename 12 | import uuid as uuid 13 | import os 14 | 15 | 16 | # Create a Flask Instance 17 | app = Flask(__name__) 18 | # Add CKEditor 19 | ckeditor = CKEditor(app) 20 | # Add Database 21 | # Old SQLite DB 22 | #app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' 23 | app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://fvmdxyjigwbmiu:d31d36c7613e08f7ad37a6e40007189d7f2f44fbc99234b339994780a122d870@ec2-3-214-190-189.compute-1.amazonaws.com:5432/d17b5scj97ckqe' 24 | # New MySQL DB 25 | # app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost/db_name' 26 | #app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:password123@localhost/our_users' 27 | # Secret Key! 28 | app.config['SECRET_KEY'] = "my super secret key that no one is supposed to know" 29 | # Initialize The Database 30 | 31 | UPLOAD_FOLDER = 'static/images/' 32 | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER 33 | 34 | db = SQLAlchemy(app) 35 | migrate = Migrate(app, db) 36 | 37 | # Flask_Login Stuff 38 | login_manager = LoginManager() 39 | login_manager.init_app(app) 40 | login_manager.login_view = 'login' 41 | 42 | @login_manager.user_loader 43 | def load_user(user_id): 44 | return Users.query.get(int(user_id)) 45 | 46 | # Pass Stuff To Navbar 47 | @app.context_processor 48 | def base(): 49 | form = SearchForm() 50 | return dict(form=form) 51 | 52 | # Create Admin Page 53 | @app.route('/admin') 54 | @login_required 55 | def admin(): 56 | id = current_user.id 57 | if id == 1: 58 | return render_template("admin.html") 59 | else: 60 | flash("Sorry you must be the Admin to access the Admin Page...") 61 | return redirect(url_for('dashboard')) 62 | 63 | 64 | 65 | # Create Search Function 66 | @app.route('/search', methods=["POST"]) 67 | def search(): 68 | form = SearchForm() 69 | posts = Posts.query 70 | if form.validate_on_submit(): 71 | # Get data from submitted form 72 | post.searched = form.searched.data 73 | # Query the Database 74 | posts = posts.filter(Posts.content.like('%' + post.searched + '%')) 75 | posts = posts.order_by(Posts.title).all() 76 | 77 | return render_template("search.html", 78 | form=form, 79 | searched = post.searched, 80 | posts = posts) 81 | # Create Login Page 82 | @app.route('/login', methods=['GET', 'POST']) 83 | def login(): 84 | form = LoginForm() 85 | if form.validate_on_submit(): 86 | user = Users.query.filter_by(username=form.username.data).first() 87 | if user: 88 | # Check the hash 89 | if check_password_hash(user.password_hash, form.password.data): 90 | login_user(user) 91 | flash("Login Succesfull!!") 92 | return redirect(url_for('dashboard')) 93 | else: 94 | flash("Wrong Password - Try Again!") 95 | else: 96 | flash("That User Doesn't Exist! Try Again...") 97 | 98 | 99 | return render_template('login.html', form=form) 100 | 101 | # Create Logout Page 102 | @app.route('/logout', methods=['GET', 'POST']) 103 | @login_required 104 | def logout(): 105 | logout_user() 106 | flash("You Have Been Logged Out! Thanks For Stopping By...") 107 | return redirect(url_for('login')) 108 | 109 | # Create Dashboard Page 110 | @app.route('/dashboard', methods=['GET', 'POST']) 111 | @login_required 112 | def dashboard(): 113 | form = UserForm() 114 | id = current_user.id 115 | name_to_update = Users.query.get_or_404(id) 116 | if request.method == "POST": 117 | name_to_update.name = request.form['name'] 118 | name_to_update.email = request.form['email'] 119 | name_to_update.favorite_color = request.form['favorite_color'] 120 | name_to_update.username = request.form['username'] 121 | name_to_update.about_author = request.form['about_author'] 122 | 123 | 124 | # Check for profile pic 125 | if request.files['profile_pic']: 126 | name_to_update.profile_pic = request.files['profile_pic'] 127 | 128 | # Grab Image Name 129 | pic_filename = secure_filename(name_to_update.profile_pic.filename) 130 | # Set UUID 131 | pic_name = str(uuid.uuid1()) + "_" + pic_filename 132 | # Save That Image 133 | saver = request.files['profile_pic'] 134 | 135 | 136 | # Change it to a string to save to db 137 | name_to_update.profile_pic = pic_name 138 | try: 139 | db.session.commit() 140 | saver.save(os.path.join(app.config['UPLOAD_FOLDER'], pic_name)) 141 | flash("User Updated Successfully!") 142 | return render_template("dashboard.html", 143 | form=form, 144 | name_to_update = name_to_update) 145 | except: 146 | flash("Error! Looks like there was a problem...try again!") 147 | return render_template("dashboard.html", 148 | form=form, 149 | name_to_update = name_to_update) 150 | else: 151 | db.session.commit() 152 | flash("User Updated Successfully!") 153 | return render_template("dashboard.html", 154 | form=form, 155 | name_to_update = name_to_update) 156 | else: 157 | return render_template("dashboard.html", 158 | form=form, 159 | name_to_update = name_to_update, 160 | id = id) 161 | 162 | return render_template('dashboard.html') 163 | 164 | 165 | 166 | 167 | 168 | 169 | @app.route('/posts/delete/') 170 | @login_required 171 | def delete_post(id): 172 | post_to_delete = Posts.query.get_or_404(id) 173 | id = current_user.id 174 | if id == post_to_delete.poster.id or id == 14: 175 | try: 176 | db.session.delete(post_to_delete) 177 | db.session.commit() 178 | 179 | # Return a message 180 | flash("Blog Post Was Deleted!") 181 | 182 | # Grab all the posts from the database 183 | posts = Posts.query.order_by(Posts.date_posted) 184 | return render_template("posts.html", posts=posts) 185 | 186 | 187 | except: 188 | # Return an error message 189 | flash("Whoops! There was a problem deleting post, try again...") 190 | 191 | # Grab all the posts from the database 192 | posts = Posts.query.order_by(Posts.date_posted) 193 | return render_template("posts.html", posts=posts) 194 | else: 195 | # Return a message 196 | flash("You Aren't Authorized To Delete That Post!") 197 | 198 | # Grab all the posts from the database 199 | posts = Posts.query.order_by(Posts.date_posted) 200 | return render_template("posts.html", posts=posts) 201 | 202 | @app.route('/posts') 203 | def posts(): 204 | # Grab all the posts from the database 205 | posts = Posts.query.order_by(Posts.date_posted) 206 | return render_template("posts.html", posts=posts) 207 | 208 | @app.route('/posts/') 209 | def post(id): 210 | post = Posts.query.get_or_404(id) 211 | return render_template('post.html', post=post) 212 | 213 | @app.route('/posts/edit/', methods=['GET', 'POST']) 214 | @login_required 215 | def edit_post(id): 216 | post = Posts.query.get_or_404(id) 217 | form = PostForm() 218 | if form.validate_on_submit(): 219 | post.title = form.title.data 220 | #post.author = form.author.data 221 | post.slug = form.slug.data 222 | post.content = form.content.data 223 | # Update Database 224 | db.session.add(post) 225 | db.session.commit() 226 | flash("Post Has Been Updated!") 227 | return redirect(url_for('post', id=post.id)) 228 | 229 | if current_user.id == post.poster_id or current_user.id == 14: 230 | form.title.data = post.title 231 | #form.author.data = post.author 232 | form.slug.data = post.slug 233 | form.content.data = post.content 234 | return render_template('edit_post.html', form=form) 235 | else: 236 | flash("You Aren't Authorized To Edit This Post...") 237 | posts = Posts.query.order_by(Posts.date_posted) 238 | return render_template("posts.html", posts=posts) 239 | 240 | 241 | 242 | # Add Post Page 243 | @app.route('/add-post', methods=['GET', 'POST']) 244 | #@login_required 245 | def add_post(): 246 | form = PostForm() 247 | 248 | if form.validate_on_submit(): 249 | poster = current_user.id 250 | post = Posts(title=form.title.data, content=form.content.data, poster_id=poster, slug=form.slug.data) 251 | # Clear The Form 252 | form.title.data = '' 253 | form.content.data = '' 254 | #form.author.data = '' 255 | form.slug.data = '' 256 | 257 | # Add post data to database 258 | db.session.add(post) 259 | db.session.commit() 260 | 261 | # Return a Message 262 | flash("Blog Post Submitted Successfully!") 263 | 264 | # Redirect to the webpage 265 | return render_template("add_post.html", form=form) 266 | 267 | 268 | 269 | # Json Thing 270 | @app.route('/date') 271 | def get_current_date(): 272 | favorite_pizza = { 273 | "John": "Pepperoni", 274 | "Mary": "Cheese", 275 | "Tim": "Mushroom" 276 | } 277 | return favorite_pizza 278 | #return {"Date": date.today()} 279 | 280 | 281 | 282 | 283 | 284 | 285 | @app.route('/delete/') 286 | @login_required 287 | def delete(id): 288 | # Check logged in id vs. id to delete 289 | if id == current_user.id: 290 | user_to_delete = Users.query.get_or_404(id) 291 | name = None 292 | form = UserForm() 293 | 294 | try: 295 | db.session.delete(user_to_delete) 296 | db.session.commit() 297 | flash("User Deleted Successfully!!") 298 | 299 | our_users = Users.query.order_by(Users.date_added) 300 | return render_template("add_user.html", 301 | form=form, 302 | name=name, 303 | our_users=our_users) 304 | 305 | except: 306 | flash("Whoops! There was a problem deleting user, try again...") 307 | return render_template("add_user.html", 308 | form=form, name=name,our_users=our_users) 309 | else: 310 | flash("Sorry, you can't delete that user! ") 311 | return redirect(url_for('dashboard')) 312 | 313 | # Update Database Record 314 | @app.route('/update/', methods=['GET', 'POST']) 315 | @login_required 316 | def update(id): 317 | form = UserForm() 318 | name_to_update = Users.query.get_or_404(id) 319 | if request.method == "POST": 320 | name_to_update.name = request.form['name'] 321 | name_to_update.email = request.form['email'] 322 | name_to_update.favorite_color = request.form['favorite_color'] 323 | name_to_update.username = request.form['username'] 324 | try: 325 | db.session.commit() 326 | flash("User Updated Successfully!") 327 | return render_template("update.html", 328 | form=form, 329 | name_to_update = name_to_update, id=id) 330 | except: 331 | flash("Error! Looks like there was a problem...try again!") 332 | return render_template("update.html", 333 | form=form, 334 | name_to_update = name_to_update, 335 | id=id) 336 | else: 337 | return render_template("update.html", 338 | form=form, 339 | name_to_update = name_to_update, 340 | id = id) 341 | 342 | 343 | 344 | #def index(): 345 | # return "

Hello World!

" 346 | 347 | # FILTERS!!! 348 | #safe 349 | #capitalize 350 | #lower 351 | #upper 352 | #title 353 | #trim 354 | #striptags 355 | 356 | 357 | @app.route('/user/add', methods=['GET', 'POST']) 358 | def add_user(): 359 | name = None 360 | form = UserForm() 361 | if form.validate_on_submit(): 362 | user = Users.query.filter_by(email=form.email.data).first() 363 | if user is None: 364 | # Hash the password!!! 365 | hashed_pw = generate_password_hash(form.password_hash.data, "sha256") 366 | user = Users(username=form.username.data, name=form.name.data, email=form.email.data, favorite_color=form.favorite_color.data, password_hash=hashed_pw) 367 | db.session.add(user) 368 | db.session.commit() 369 | name = form.name.data 370 | form.name.data = '' 371 | form.username.data = '' 372 | form.email.data = '' 373 | form.favorite_color.data = '' 374 | form.password_hash.data = '' 375 | 376 | flash("User Added Successfully!") 377 | our_users = Users.query.order_by(Users.date_added) 378 | return render_template("add_user.html", 379 | form=form, 380 | name=name, 381 | our_users=our_users) 382 | 383 | # Create a route decorator 384 | @app.route('/') 385 | def index(): 386 | first_name = "John" 387 | stuff = "This is bold text" 388 | 389 | favorite_pizza = ["Pepperoni", "Cheese", "Mushrooms", 41] 390 | return render_template("index.html", 391 | first_name=first_name, 392 | stuff=stuff, 393 | favorite_pizza = favorite_pizza) 394 | 395 | # localhost:5000/user/John 396 | @app.route('/user/') 397 | 398 | def user(name): 399 | return render_template("user.html", user_name=name) 400 | 401 | # Create Custom Error Pages 402 | 403 | # Invalid URL 404 | @app.errorhandler(404) 405 | def page_not_found(e): 406 | return render_template("404.html"), 404 407 | 408 | # Internal Server Error 409 | @app.errorhandler(500) 410 | def page_not_found(e): 411 | return render_template("500.html"), 500 412 | 413 | # Create Password Test Page 414 | @app.route('/test_pw', methods=['GET', 'POST']) 415 | def test_pw(): 416 | email = None 417 | password = None 418 | pw_to_check = None 419 | passed = None 420 | form = PasswordForm() 421 | 422 | 423 | # Validate Form 424 | if form.validate_on_submit(): 425 | email = form.email.data 426 | password = form.password_hash.data 427 | # Clear the form 428 | form.email.data = '' 429 | form.password_hash.data = '' 430 | 431 | # Lookup User By Email Address 432 | pw_to_check = Users.query.filter_by(email=email).first() 433 | 434 | # Check Hashed Password 435 | passed = check_password_hash(pw_to_check.password_hash, password) 436 | 437 | return render_template("test_pw.html", 438 | email = email, 439 | password = password, 440 | pw_to_check = pw_to_check, 441 | passed = passed, 442 | form = form) 443 | 444 | 445 | # Create Name Page 446 | @app.route('/name', methods=['GET', 'POST']) 447 | def name(): 448 | name = None 449 | form = NamerForm() 450 | # Validate Form 451 | if form.validate_on_submit(): 452 | name = form.name.data 453 | form.name.data = '' 454 | flash("Form Submitted Successfully!") 455 | 456 | return render_template("name.html", 457 | name = name, 458 | form = form) 459 | 460 | 461 | 462 | 463 | # Create a Blog Post model 464 | class Posts(db.Model): 465 | id = db.Column(db.Integer, primary_key=True) 466 | title = db.Column(db.String(255)) 467 | content = db.Column(db.Text) 468 | #author = db.Column(db.String(255)) 469 | date_posted = db.Column(db.DateTime, default=datetime.utcnow) 470 | slug = db.Column(db.String(255)) 471 | # Foreign Key To Link Users (refer to primary key of the user) 472 | poster_id = db.Column(db.Integer, db.ForeignKey('users.id')) 473 | 474 | # Create Model 475 | class Users(db.Model, UserMixin): 476 | id = db.Column(db.Integer, primary_key=True) 477 | username = db.Column(db.String(20), nullable=False, unique=True) 478 | name = db.Column(db.String(200), nullable=False) 479 | email = db.Column(db.String(120), nullable=False, unique=True) 480 | favorite_color = db.Column(db.String(120)) 481 | about_author = db.Column(db.Text(), nullable=True) 482 | date_added = db.Column(db.DateTime, default=datetime.utcnow) 483 | profile_pic = db.Column(db.String(), nullable=True) 484 | 485 | # Do some password stuff! 486 | password_hash = db.Column(db.String(128)) 487 | # User Can Have Many Posts 488 | posts = db.relationship('Posts', backref='poster') 489 | 490 | 491 | @property 492 | def password(self): 493 | raise AttributeError('password is not a readable attribute!') 494 | 495 | @password.setter 496 | def password(self, password): 497 | self.password_hash = generate_password_hash(password) 498 | 499 | def verify_password(self, password): 500 | return check_password_hash(self.password_hash, password) 501 | 502 | # Create A String 503 | def __repr__(self): 504 | return '' % self.name 505 | 506 | -------------------------------------------------------------------------------- /create_db.py: -------------------------------------------------------------------------------- 1 | import mysql.connector 2 | 3 | mydb = mysql.connector.connect( 4 | host="localhost", 5 | user="root", 6 | passwd = "password123", 7 | ) 8 | 9 | my_cursor = mydb.cursor() 10 | 11 | #my_cursor.execute("CREATE DATABASE our_users") 12 | 13 | my_cursor.execute("SHOW DATABASES") 14 | for db in my_cursor: 15 | print(db) 16 | 17 | -------------------------------------------------------------------------------- /migrations/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. -------------------------------------------------------------------------------- /migrations/alembic.ini: -------------------------------------------------------------------------------- 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,flask_migrate 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 | [logger_flask_migrate] 38 | level = INFO 39 | handlers = 40 | qualname = flask_migrate 41 | 42 | [handler_console] 43 | class = StreamHandler 44 | args = (sys.stderr,) 45 | level = NOTSET 46 | formatter = generic 47 | 48 | [formatter_generic] 49 | format = %(levelname)-5.5s [%(name)s] %(message)s 50 | datefmt = %H:%M:%S 51 | -------------------------------------------------------------------------------- /migrations/env.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | 3 | import logging 4 | from logging.config import fileConfig 5 | 6 | from flask import current_app 7 | 8 | from alembic import context 9 | 10 | # this is the Alembic Config object, which provides 11 | # access to the values within the .ini file in use. 12 | config = context.config 13 | 14 | # Interpret the config file for Python logging. 15 | # This line sets up loggers basically. 16 | fileConfig(config.config_file_name) 17 | logger = logging.getLogger('alembic.env') 18 | 19 | # add your model's MetaData object here 20 | # for 'autogenerate' support 21 | # from myapp import mymodel 22 | # target_metadata = mymodel.Base.metadata 23 | config.set_main_option( 24 | 'sqlalchemy.url', 25 | str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%')) 26 | target_metadata = current_app.extensions['migrate'].db.metadata 27 | 28 | # other values from the config, defined by the needs of env.py, 29 | # can be acquired: 30 | # my_important_option = config.get_main_option("my_important_option") 31 | # ... etc. 32 | 33 | 34 | def run_migrations_offline(): 35 | """Run migrations in 'offline' mode. 36 | 37 | This configures the context with just a URL 38 | and not an Engine, though an Engine is acceptable 39 | here as well. By skipping the Engine creation 40 | we don't even need a DBAPI to be available. 41 | 42 | Calls to context.execute() here emit the given string to the 43 | script output. 44 | 45 | """ 46 | url = config.get_main_option("sqlalchemy.url") 47 | context.configure( 48 | url=url, target_metadata=target_metadata, literal_binds=True 49 | ) 50 | 51 | with context.begin_transaction(): 52 | context.run_migrations() 53 | 54 | 55 | def run_migrations_online(): 56 | """Run migrations in 'online' mode. 57 | 58 | In this scenario we need to create an Engine 59 | and associate a connection with the context. 60 | 61 | """ 62 | 63 | # this callback is used to prevent an auto-migration from being generated 64 | # when there are no changes to the schema 65 | # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html 66 | def process_revision_directives(context, revision, directives): 67 | if getattr(config.cmd_opts, 'autogenerate', False): 68 | script = directives[0] 69 | if script.upgrade_ops.is_empty(): 70 | directives[:] = [] 71 | logger.info('No changes in schema detected.') 72 | 73 | connectable = current_app.extensions['migrate'].db.engine 74 | 75 | with connectable.connect() as connection: 76 | context.configure( 77 | connection=connection, 78 | target_metadata=target_metadata, 79 | process_revision_directives=process_revision_directives, 80 | **current_app.extensions['migrate'].configure_args 81 | ) 82 | 83 | with context.begin_transaction(): 84 | context.run_migrations() 85 | 86 | 87 | if context.is_offline_mode(): 88 | run_migrations_offline() 89 | else: 90 | run_migrations_online() 91 | -------------------------------------------------------------------------------- /migrations/script.py.mako: -------------------------------------------------------------------------------- 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"} 25 | -------------------------------------------------------------------------------- /migrations/versions/5f8bac49757f_about_author_added.py: -------------------------------------------------------------------------------- 1 | """about author added 2 | 3 | Revision ID: 5f8bac49757f 4 | Revises: e47c843a6860 5 | Create Date: 2021-12-16 09:07:06.692810 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = '5f8bac49757f' 14 | down_revision = 'e47c843a6860' 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | # ### commands auto generated by Alembic - please adjust! ### 21 | op.add_column('users', sa.Column('about_author', sa.Text(length=500), nullable=True)) 22 | # ### end Alembic commands ### 23 | 24 | 25 | def downgrade(): 26 | # ### commands auto generated by Alembic - please adjust! ### 27 | op.drop_column('users', 'about_author') 28 | # ### end Alembic commands ### 29 | -------------------------------------------------------------------------------- /migrations/versions/a7bc9bb228d8_added_profile_pic.py: -------------------------------------------------------------------------------- 1 | """added profile pic 2 | 3 | Revision ID: a7bc9bb228d8 4 | Revises: 5f8bac49757f 5 | Create Date: 2022-01-07 11:33:16.232214 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = 'a7bc9bb228d8' 14 | down_revision = '5f8bac49757f' 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | # ### commands auto generated by Alembic - please adjust! ### 21 | op.add_column('users', sa.Column('profile_pic', sa.String(), nullable=True)) 22 | # ### end Alembic commands ### 23 | 24 | 25 | def downgrade(): 26 | # ### commands auto generated by Alembic - please adjust! ### 27 | op.drop_column('users', 'profile_pic') 28 | # ### end Alembic commands ### 29 | -------------------------------------------------------------------------------- /migrations/versions/e47c843a6860_remove_author.py: -------------------------------------------------------------------------------- 1 | """remove author 2 | 3 | Revision ID: e47c843a6860 4 | Revises: f26432df1173 5 | Create Date: 2021-09-23 10:49:17.193074 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = 'e47c843a6860' 14 | down_revision = 'f26432df1173' 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | # ### commands auto generated by Alembic - please adjust! ### 21 | op.drop_column('posts', 'author') 22 | # ### end Alembic commands ### 23 | 24 | 25 | def downgrade(): 26 | # ### commands auto generated by Alembic - please adjust! ### 27 | op.add_column('posts', sa.Column('author', sa.VARCHAR(length=255), nullable=True)) 28 | # ### end Alembic commands ### 29 | -------------------------------------------------------------------------------- /migrations/versions/f26432df1173_add_foreign_key.py: -------------------------------------------------------------------------------- 1 | """add foreign key 2 | 3 | Revision ID: f26432df1173 4 | Revises: 5 | Create Date: 2021-09-23 10:41:50.082818 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = 'f26432df1173' 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.add_column('posts', sa.Column('author', sa.String(length=255), nullable=True)) 22 | # ### end Alembic commands ### 23 | 24 | 25 | def downgrade(): 26 | # ### commands auto generated by Alembic - please adjust! ### 27 | op.drop_column('posts', 'author') 28 | # ### end Alembic commands ### 29 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | alembic==1.5.8 2 | cffi==1.14.5 3 | click==7.1.2 4 | cryptography==3.4.6 5 | Flask==1.1.2 6 | Flask-CKEditor==0.4.6 7 | Flask-Login==0.5.0 8 | Flask-Migrate==2.7.0 9 | Flask-SQLAlchemy==2.4.4 10 | Flask-WTF==0.14.3 11 | gunicorn==20.1.0 12 | itsdangerous==1.1.0 13 | Jinja2==2.11.2 14 | Mako==1.1.4 15 | MarkupSafe==1.1.1 16 | mysql-connector==2.2.9 17 | mysql-connector-python==8.0.23 18 | protobuf==3.15.5 19 | psycopg2==2.9.3 20 | pycparser==2.20 21 | PyMySQL==1.0.2 22 | python-dateutil==2.8.1 23 | python-editor==1.0.4 24 | six==1.15.0 25 | SQLAlchemy==1.3.23 26 | Werkzeug==1.0.1 27 | WTForms==2.3.3 28 | -------------------------------------------------------------------------------- /static/css/style.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: darkblue; 3 | font-size:60px; 4 | } 5 | 6 | body { 7 | background: #f4f4f4; 8 | } 9 | 10 | #demo{ 11 | font-size: 12px; 12 | color: darkblue; 13 | } -------------------------------------------------------------------------------- /static/images/4b927b0b-7f8f-11ec-8fe3-34e894657787_my_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/4b927b0b-7f8f-11ec-8fe3-34e894657787_my_profile.png -------------------------------------------------------------------------------- /static/images/54d448aa-8518-11ec-a2a5-34e894657787_planking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/54d448aa-8518-11ec-a2a5-34e894657787_planking.png -------------------------------------------------------------------------------- /static/images/5cfef60e-8518-11ec-b98c-34e894657787_my_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/5cfef60e-8518-11ec-b98c-34e894657787_my_profile.png -------------------------------------------------------------------------------- /static/images/7978f08c-8a91-11ec-a01e-34e894657787_my_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/7978f08c-8a91-11ec-a01e-34e894657787_my_profile.png -------------------------------------------------------------------------------- /static/images/NorthPeak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/NorthPeak.png -------------------------------------------------------------------------------- /static/images/dbbaecd1-8517-11ec-a660-34e894657787_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/dbbaecd1-8517-11ec-a660-34e894657787_ -------------------------------------------------------------------------------- /static/images/default_profile_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/default_profile_pic.png -------------------------------------------------------------------------------- /static/images/e58ac37a-7f8e-11ec-86c2-34e894657787_my_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/e58ac37a-7f8e-11ec-86c2-34e894657787_my_profile.png -------------------------------------------------------------------------------- /static/images/efd91395-7f8e-11ec-821c-34e894657787_pool.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/efd91395-7f8e-11ec-821c-34e894657787_pool.jpg -------------------------------------------------------------------------------- /static/images/f095ba31-8517-11ec-ae00-34e894657787_my_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/static/images/f095ba31-8517-11ec-ae00-34e894657787_my_profile.png -------------------------------------------------------------------------------- /static/js/myfile.js: -------------------------------------------------------------------------------- 1 | document.getElementById('demo').innerHTML = "This was created with Javascript"; -------------------------------------------------------------------------------- /templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |

404 Error

8 |

Page Not Found - Try Again...

9 | 10 |
11 | 12 | {% endblock %} -------------------------------------------------------------------------------- /templates/500.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |

500 Internal Server Error

8 |

Something Went Wrong! Try Again...

9 | 10 |
11 | 12 | {% endblock %} -------------------------------------------------------------------------------- /templates/add_post.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | 6 | 7 | 8 | {% for message in get_flashed_messages() %} 9 | 13 | {% endfor %} 14 | 15 | {% if current_user.is_authenticated %} 16 | 17 |

Add Blog Post...

18 |
19 |
20 |
21 | {{ form.hidden_tag() }} 22 | 23 | {{ form.title.label(class="form-label") }} 24 | 25 | {{ form.title(class="form-control") }} 26 |
27 | 28 | 29 | {{ form.slug.label(class="form-label") }} 30 | 31 | {{ form.slug(class="form-control") }} 32 |
33 | 34 | {{ form.content.label(class="form-label") }} 35 | 36 | {{ form.content(class="form-control", rows="10") }} 37 |
38 | 39 | 40 | {{ form.submit(class="btn btn-secondary") }} 41 | 42 | 43 |
44 | {{ ckeditor.load() }} 45 | {{ ckeditor.config(name='content') }} 46 | 47 |
48 | {% else %} 49 |

Must Be Logged In...

50 |

Sorry, You must be logged in to access this page!

51 | 52 | Login Here 53 | 54 | {% endif %} 55 | 56 | 57 | {% endblock %} -------------------------------------------------------------------------------- /templates/add_user.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | {% for message in get_flashed_messages() %} 6 | 7 | 11 | 12 | 13 | {% endfor %} 14 | 15 | 16 | {% if name %} 17 |

User Added!

18 |

19 | 20 | 21 | {% for our_user in our_users %} 22 | 23 | 25 | 26 | {% endfor %} 27 | 28 |
{{ our_user.id }}. {{ our_user.name }} - {{ our_user.email }} - {{ our_user.favorite_color }} - 24 | Delete
29 | 30 | 31 | {% else %} 32 |

User List:

33 |
34 |
35 |
36 | {{ form.hidden_tag() }} 37 | 38 | {{ form.name.label(class="form-label") }} 39 | 40 | {{ form.name(class="form-control") }} 41 |
42 | 43 | {{ form.username.label(class="form-label") }} 44 | 45 | {{ form.username(class="form-control") }} 46 |
47 | 48 | {{ form.email.label(class="form-label") }} 49 | 50 | {{ form.email(class="form-control") }} 51 |
52 | 53 | {{ form.favorite_color.label(class="form-label") }} 54 | 55 | {{ form.favorite_color(class="form-control") }} 56 |
57 | 58 | {{ form.password_hash.label(class="form-label") }} 59 | 60 | {{ form.password_hash(class="form-control") }} 61 |
62 | 63 | {{ form.password_hash2.label(class="form-label") }} 64 | 65 | {{ form.password_hash2(class="form-control") }} 66 |
67 | 68 | {{ form.submit(class="btn btn-secondary") }} 69 | 70 | 71 |
72 |
73 |


74 | 75 | 76 | {% for our_user in our_users %} 77 | 78 | 81 | 82 | {% endfor %} 83 | 84 |
{{ our_user.id }}. {{ our_user.name }} - {{our_user.username }} - {{ our_user.email }} - {{ our_user.favorite_color }} - 79 | PW: {{ our_user.password_hash }} - 80 | Delete
85 | {% endif %} 86 | 87 | {% endblock %} -------------------------------------------------------------------------------- /templates/admin.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Admin Area

6 |

Do some Admin-y type things here...

7 | 8 | {% endblock %} -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Flasker! 16 | 17 | 18 | {% include 'navbar.html' %} 19 |
20 |
21 | {% block content %} 22 | {% endblock %} 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /templates/dashboard.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | {% for message in get_flashed_messages() %} 6 | 7 | 11 | 12 | 13 | {% endfor %} 14 | 15 | 16 | 17 |

Dashboard

18 |
19 | 20 |
21 |
22 | {{ current_user.name }} 23 |
24 |
25 | 26 |

27 | 28 |

29 |
30 |
31 | 32 | Name: 33 | {{ current_user.name }}
34 | 35 | Username: 36 | {{ current_user.username }}
37 | 38 | User Id: 39 | {{ current_user.id }}
40 | 41 | Email: 42 | {{ current_user.email }}
43 | 44 | Favorite Color: 45 | {{ current_user.favorite_color }}
46 | 47 | About Author: 48 | {{ current_user.about_author }}
49 | 50 | Profile Pic: 51 | {{ current_user.profile_pic }}
52 | 53 | Date Joined: 54 | {{ current_user.date_added }}
55 | 56 | 57 | 58 | 59 | 60 |

61 | Logout 62 | 63 | Update Profile 64 | 65 | Delete 66 |

67 | 68 | 69 |
70 |
71 | {% if current_user.profile_pic %} 72 | 73 | 74 | 75 | {% else %} 76 | 77 | 78 | 79 | {% endif %} 80 | 81 |
82 |
83 |
84 | 85 | 86 |
87 |
88 | 89 | 90 | 91 |
92 | 93 |
94 |
95 | Update Profile 96 |
97 |
98 | 99 |
100 | {{ form.hidden_tag() }} 101 | 102 | {{ form.name.label(class="form-label") }} 103 | 104 | {{ form.name(class="form-control", value=name_to_update.name) }} 105 |
106 | 107 | {{ form.username.label(class="form-label") }} 108 | 109 | {{ form.username(class="form-control", value=name_to_update.username) }} 110 |
111 | 112 | {{ form.email.label(class="form-label") }} 113 | 114 | {{ form.email(class="form-control", value=name_to_update.email) }} 115 |
116 | 117 | {{ form.favorite_color.label(class="form-label") }} 118 | 119 | {{ form.favorite_color(class="form-control", value=name_to_update.favorite_color) }} 120 |
121 | 122 | {{ form.about_author.label(class="form-label") }} 123 | 124 | 125 |
126 | 127 | {{ form.profile_pic.label(class="form-label") }} 128 | 129 | {{ form.profile_pic(class="form-control", value=name_to_update.profile_pic) }} 130 | 131 | 132 |
133 | 134 | {{ form.submit(class="btn btn-secondary btn-sm") }} 135 | 136 | 137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 |
145 | 146 | 147 | 148 | 149 | 150 |
151 | 152 | 153 | {% endblock %} -------------------------------------------------------------------------------- /templates/edit_post.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | {% for message in get_flashed_messages() %} 6 | 10 | {% endfor %} 11 | 12 |
13 |

Edit Post...

14 |
15 |
16 |
17 | {{ form.hidden_tag() }} 18 | 19 | {{ form.title.label(class="form-label") }} 20 | 21 | {{ form.title(class="form-control") }} 22 |
23 | 24 | 25 | {{ form.slug.label(class="form-label") }} 26 | 27 | {{ form.slug(class="form-control") }} 28 |
29 | 30 | {{ form.content.label(class="form-label") }} 31 | 32 | {{ form.content(class="form-control", rows="10") }} 33 |
34 | 35 | 36 | {{ form.submit(class="btn btn-secondary") }} 37 | 38 | 39 |
40 | {{ ckeditor.load() }} 41 | {{ ckeditor.config(name='content') }} 42 | 43 | 44 |
45 | 46 | Back To Blog 47 | 48 | 49 | 50 | 51 | 52 | {% endblock %} -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Hello World!

6 | 7 |

This is my first webpage!!!

8 | 9 |

My name is {{ first_name }}

10 | 11 |

{{ stuff|title }}

12 | 13 |

Favorite Pizza:

14 | 15 | {% for topping in favorite_pizza %} 16 | 17 | {% if topping == 41 %} 18 | {{ topping + 100 }}
19 | {% else %} 20 | {{ topping }}
21 | {% endif %} 22 | 23 | 24 | {% endfor %} 25 | 26 |

27 | 28 | 29 | 30 | {% endblock %} -------------------------------------------------------------------------------- /templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | {% for message in get_flashed_messages() %} 6 | 7 | 11 | 12 | 13 | {% endfor %} 14 | 15 | 16 | 17 |

Login!

18 |

19 | 20 | 21 | 22 |
23 |
24 | {{ form.hidden_tag() }} 25 | 26 | {{ form.username.label(class="form-label") }} 27 | 28 | {{ form.username(class="form-control") }} 29 |
30 | 31 | {{ form.password.label(class="form-label") }} 32 | 33 | {{ form.password(class="form-control") }} 34 |
35 | 36 | 37 |
38 | 39 | {{ form.submit(class="btn btn-secondary") }} 40 | 41 | 42 |
43 |
44 | 45 | 46 | {% endblock %} -------------------------------------------------------------------------------- /templates/name.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | {% for message in get_flashed_messages() %} 6 | 7 | 11 | 12 | 13 | {% endfor %} 14 | 15 | 16 | {% if name %} 17 |

Hello {{ name }}!!

18 |
19 | 20 |

21 |

This is stuff...

22 | 23 | 24 | 25 | 26 | {% else %} 27 |

What's Your Name?

28 |
29 |
30 | {{ form.hidden_tag() }} 31 | 32 | {{ form.name.label(class="form-label") }} 33 | 34 | {{ form.name(class="form-control") }} 35 |
36 | 37 | {{ form.submit(class="btn btn-secondary") }} 38 | 39 | 40 |
41 | 42 | 43 | 44 | {% endif %} 45 | 46 | {% endblock %} -------------------------------------------------------------------------------- /templates/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/post.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | {% for message in get_flashed_messages() %} 6 | 10 | {% endfor %} 11 | 12 |
13 | 14 |
15 |

{{ post.title }}

16 | By: {{ post.poster.name }}
17 | {{ post.date_posted }}


18 | 19 | {{ post.content|safe }}

20 | 21 | 22 |
23 |
24 |
25 | {% if post.poster.profile_pic %} 26 | 27 | {% else %} 28 | 29 | {% endif %} 30 |
31 | 32 |
33 |
34 |
35 | {{ post.poster.name }} 36 |
37 |

38 | {% if post.poster.about_author %} 39 | {{ post.poster.about_author }} 40 | {% else %} 41 | Author has no about profile yet... 42 | {% endif %} 43 | 44 |

45 |
46 |
47 |
48 |
49 | 50 |
51 | 52 | {% if post.poster_id == current_user.id %} 53 | 54 | Edit Post 55 | 56 | Delete Post 57 | 58 | {% endif %} 59 | 60 | Back To Blog 61 | 62 | 63 | 64 | 65 | 66 | {% endblock %} -------------------------------------------------------------------------------- /templates/posts.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | {% for message in get_flashed_messages() %} 6 | 10 | {% endfor %} 11 | 12 |
13 | {% for post in posts %} 14 |
15 |

{{ post.title }}

16 | By: {{ post.poster.name }}
17 | {{ post.date_posted }}


18 | 19 | {{ post.content|safe }} 20 |

21 | View Post 22 | 23 | {% if post.poster_id == current_user.id or current_user.id == 14 %} 24 | Edit Post 25 | 26 | Delete Post 27 | 28 | {% endif %} 29 | 30 |

31 |
32 |
33 | {% endfor %} 34 | 35 | 36 | 37 | 38 | 39 | {% endblock %} -------------------------------------------------------------------------------- /templates/search.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |

You Searched For: {{ searched }}

7 | 8 |
9 | 10 | {% if posts %} 11 | 12 | {% for post in posts %} 13 |
14 |

{{ post.title }}

15 | By: {{ post.poster.name }}
16 | {{ post.date_posted }}


17 | 18 | {{ post.content|safe }} 19 |

20 | View Post 21 | 22 | {% if post.poster_id == current_user.id %} 23 | Edit Post 24 | 25 | Delete Post 26 | 27 | {% endif %} 28 | 29 |

30 |
31 |
32 | {% endfor %} 33 | 34 | {% else %} 35 | Sorry, your search term: {{ searched }} was not found... 36 | {% endif %} 37 | {% endblock %} -------------------------------------------------------------------------------- /templates/test_pw.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | {% for message in get_flashed_messages() %} 6 | 7 | 11 | 12 | 13 | {% endfor %} 14 | 15 | 16 | {% if email %} 17 |

Email: {{ email }}

18 |

Password: {{ password }}

19 |
20 |

I found this info:

21 | Name: {{pw_to_check.name}}
22 | Email: {{pw_to_check.email}}
23 | PW: {{pw_to_check.password_hash}}
24 |
25 | Passed: {{ passed }} 26 | 27 | 28 | {% else %} 29 |

What's Your Email and Password?

30 |
31 |
32 | {{ form.hidden_tag() }} 33 | 34 | {{ form.email.label(class="form-label") }} 35 | 36 | {{ form.email(class="form-control") }} 37 |
38 | 39 | {{ form.password_hash.label(class="form-label") }} 40 | 41 | {{ form.password_hash(class="form-control") }} 42 |
43 | 44 | {{ form.submit(class="btn btn-secondary") }} 45 | 46 | 47 |
48 | 49 | 50 | 51 | {% endif %} 52 | 53 | {% endblock %} -------------------------------------------------------------------------------- /templates/update.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 | {% for message in get_flashed_messages() %} 6 | 7 | 11 | 12 | 13 | {% endfor %} 14 | 15 | {% if id == current_user.id %} 16 | 17 |

Update User...

18 |
19 |
20 |
21 | {{ form.hidden_tag() }} 22 | 23 | {{ form.name.label(class="form-label") }} 24 | 25 | {{ form.name(class="form-control", value=name_to_update.name) }} 26 |
27 | 28 | {{ form.username.label(class="form-label") }} 29 | 30 | {{ form.username(class="form-control", value=name_to_update.username) }} 31 |
32 | 33 | {{ form.email.label(class="form-label") }} 34 | 35 | {{ form.email(class="form-control", value=name_to_update.email) }} 36 |
37 | 38 | {{ form.favorite_color.label(class="form-label") }} 39 | 40 | {{ form.favorite_color(class="form-control", value=name_to_update.favorite_color) }} 41 | 42 | 43 | 44 |
45 | 46 | {{ form.submit(class="btn btn-secondary") }} 47 | 48 | Delete 49 | 50 | 51 |
52 |
53 |


54 | 55 | {% else %} 56 | 60 | 61 |

Access Denied!

62 |

Sorry, you cannot access this user profile...

63 | 64 | {% endif %} 65 | 66 | 67 | {% endblock %} -------------------------------------------------------------------------------- /templates/user.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Hello {{ user_name|title }}

6 | 7 | {% endblock %} -------------------------------------------------------------------------------- /users.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flatplanet/flasker/a92daf038df85cf0d4eae3668fe00a246ce8c76f/users.db -------------------------------------------------------------------------------- /webforms.py: -------------------------------------------------------------------------------- 1 | from flask_wtf import FlaskForm 2 | from wtforms import StringField, SubmitField, PasswordField, BooleanField, ValidationError, TextAreaField 3 | from wtforms.validators import DataRequired, EqualTo, Length 4 | from wtforms.widgets import TextArea 5 | from flask_ckeditor import CKEditorField 6 | from flask_wtf.file import FileField 7 | 8 | # Create A Search Form 9 | class SearchForm(FlaskForm): 10 | searched = StringField("Searched", validators=[DataRequired()]) 11 | submit = SubmitField("Submit") 12 | 13 | 14 | # Create Login Form 15 | class LoginForm(FlaskForm): 16 | username = StringField("Username", validators=[DataRequired()]) 17 | password = PasswordField("Password", validators=[DataRequired()]) 18 | submit = SubmitField("Submit") 19 | 20 | 21 | # Create a Posts Form 22 | class PostForm(FlaskForm): 23 | title = StringField("Title", validators=[DataRequired()]) 24 | #content = StringField("Content", validators=[DataRequired()], widget=TextArea()) 25 | content = CKEditorField('Content', validators=[DataRequired()]) 26 | 27 | #author = StringField("Author") 28 | slug = StringField("Slug", validators=[DataRequired()]) 29 | submit = SubmitField("Submit") 30 | 31 | # Create a Form Class 32 | class UserForm(FlaskForm): 33 | name = StringField("Name", validators=[DataRequired()]) 34 | username = StringField("Username", validators=[DataRequired()]) 35 | email = StringField("Email", validators=[DataRequired()]) 36 | favorite_color = StringField("Favorite Color") 37 | about_author = TextAreaField("About Author") 38 | password_hash = PasswordField('Password', validators=[DataRequired(), EqualTo('password_hash2', message='Passwords Must Match!')]) 39 | password_hash2 = PasswordField('Confirm Password', validators=[DataRequired()]) 40 | profile_pic = FileField("Profile Pic") 41 | submit = SubmitField("Submit") 42 | 43 | class PasswordForm(FlaskForm): 44 | email = StringField("What's Your Email", validators=[DataRequired()]) 45 | password_hash = PasswordField("What's Your Password", validators=[DataRequired()]) 46 | submit = SubmitField("Submit") 47 | 48 | # Create a Form Class 49 | class NamerForm(FlaskForm): 50 | name = StringField("What's Your Name", validators=[DataRequired()]) 51 | submit = SubmitField("Submit") 52 | 53 | # BooleanField 54 | # DateField 55 | # DateTimeField 56 | # DecimalField 57 | # FileField 58 | # HiddenField 59 | # MultipleField 60 | # FieldList 61 | # FloatField 62 | # FormField 63 | # IntegerField 64 | # PasswordField 65 | # RadioField 66 | # SelectField 67 | # SelectMultipleField 68 | # SubmitField 69 | # StringField 70 | # TextAreaField 71 | 72 | ## Validators 73 | # DataRequired 74 | # Email 75 | # EqualTo 76 | # InputRequired 77 | # IPAddress 78 | # Length 79 | # MacAddress 80 | # NumberRange 81 | # Optional 82 | # Regexp 83 | # URL 84 | # UUID 85 | # AnyOf 86 | # NoneOf 87 | --------------------------------------------------------------------------------