programmeerles-ouderen

Teach programming to seniors
Log | Files | Refs

commit c6f746d38760df623970d9d4e63897ed90838003
parent 8f6e5386445b1a24dff7043e27eadf1e56d765b1
Author: Friedel Schön <[email protected]>
Date:   Mon,  4 Apr 2022 14:17:22 +0200

programmeerles -> flaskblog

Diffstat:
Rprogrammeerles/__init__.py -> flaskblog/__init__.py | 0
Aflaskblog/forms.py | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aflaskblog/models.py | 43+++++++++++++++++++++++++++++++++++++++++++
Aflaskblog/routes.py | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rprogrammeerles/site.db -> flaskblog/site.db | 0
Rprogrammeerles/static/main.css -> flaskblog/static/main.css | 0
Rprogrammeerles/static/profile_pics/2e32b4c96a8d8f10.jpg -> flaskblog/static/profile_pics/2e32b4c96a8d8f10.jpg | 0
Rprogrammeerles/static/profile_pics/4895353c1045b870.jpg -> flaskblog/static/profile_pics/4895353c1045b870.jpg | 0
Rprogrammeerles/static/profile_pics/4c4083a8362b3c0a.jpg -> flaskblog/static/profile_pics/4c4083a8362b3c0a.jpg | 0
Rprogrammeerles/static/profile_pics/53998538edf2342c.png -> flaskblog/static/profile_pics/53998538edf2342c.png | 0
Rprogrammeerles/static/profile_pics/6809465dffb2e5ba.jpg -> flaskblog/static/profile_pics/6809465dffb2e5ba.jpg | 0
Rprogrammeerles/static/profile_pics/7798432669b8b3ac.jpg -> flaskblog/static/profile_pics/7798432669b8b3ac.jpg | 0
Rprogrammeerles/static/profile_pics/85ed1b444539873d.png -> flaskblog/static/profile_pics/85ed1b444539873d.png | 0
Rprogrammeerles/static/profile_pics/b6e1c53325f88b74.png -> flaskblog/static/profile_pics/b6e1c53325f88b74.png | 0
Rprogrammeerles/static/profile_pics/default.jpg -> flaskblog/static/profile_pics/default.jpg | 0
Rprogrammeerles/templates/about.html -> flaskblog/templates/about.html | 0
Rprogrammeerles/templates/account.html -> flaskblog/templates/account.html | 0
Rprogrammeerles/templates/create_post.html -> flaskblog/templates/create_post.html | 0
Rprogrammeerles/templates/home1.html -> flaskblog/templates/home1.html | 0
Rprogrammeerles/templates/index.html -> flaskblog/templates/index.html | 0
Rprogrammeerles/templates/layout.html -> flaskblog/templates/layout.html | 0
Rprogrammeerles/templates/login.html -> flaskblog/templates/login.html | 0
Rprogrammeerles/templates/post.html -> flaskblog/templates/post.html | 0
Rprogrammeerles/templates/register.html -> flaskblog/templates/register.html | 0
Rprogrammeerles/templates/user_post.html -> flaskblog/templates/user_post.html | 0
Dprogrammeerles/forms.py | 60------------------------------------------------------------
Dprogrammeerles/models.py | 43-------------------------------------------
Dprogrammeerles/routes.py | 149-------------------------------------------------------------------------------
Mrun.py | 2+-
29 files changed, 259 insertions(+), 253 deletions(-)

diff --git a/programmeerles/__init__.py b/flaskblog/__init__.py diff --git a/flaskblog/forms.py b/flaskblog/forms.py @@ -0,0 +1,59 @@ +from flask_wtf import FlaskForm +from flask_wtf.file import FileField, FileAllowed +from flask_login import current_user +from wtforms import StringField, PasswordField, SubmitField, BooleanField, TextAreaField +from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError +from .models import User + + +class RegistrationForm(FlaskForm): + username = StringField('Username', + validators=[DataRequired(), Length(min=2, max=20)]) + email = StringField('Email', + validators=[DataRequired(), Email()]) + password = PasswordField('Password', validators=[DataRequired()]) + confirm_password = PasswordField('Confirm Password', + validators=[DataRequired(), EqualTo('password')]) + submit = SubmitField('Sign Up') + + def validate_username(self, username): + user = User.query.filter_by(username=username.data).first() + if user: + raise ValidationError('That username is taken. Please choose a different one.') + + def validate_email(self, email): + user = User.query.filter_by(email=email.data).first() + if user: + raise ValidationError('That email is taken. Please choose a different one.') + + +class LoginForm(FlaskForm): + email = StringField('Email', + validators=[DataRequired(), Email()]) + password = PasswordField('Password', validators=[DataRequired()]) + remember = BooleanField('Remember Me') + submit = SubmitField('Login') + +class UpdateAccountForm(FlaskForm): + username = StringField('Username', + validators=[DataRequired(), Length(min=2, max=20)]) + email = StringField('Email', + validators=[DataRequired(), Email()]) + picture = FileField('Update Profile Picture',validators=[FileAllowed(['jpg','png'])]) + submit = SubmitField('Update') + + def validate_username(self, username): + if username.data != current_user.username: + user = User.query.filter_by(username=username.data).first() + if user: + raise ValidationError('That username is taken. Please choose a different one.') + + def validate_email(self, email): + if email.data != current_user.email: + user = User.query.filter_by(email=email.data).first() + if user: + raise ValidationError('That email is taken. Please choose a different one.') +class PostForm(FlaskForm): + title = StringField('Title', validators=[DataRequired()]) + content = TextAreaField('Content', validators=[DataRequired()]) + submit = SubmitField('Post') +\ No newline at end of file diff --git a/flaskblog/models.py b/flaskblog/models.py @@ -0,0 +1,43 @@ +from datetime import datetime +from . import db, login_manager +from flask_login import UserMixin + + +@login_manager.user_loader +def load_user(user_id): + return User.query.get(int(user_id)) + + +class User(db.Model, UserMixin): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(20), unique=True, nullable=False) + email = db.Column(db.String(120), unique=True, nullable=False) + image_file = db.Column(db.String(20), nullable=False, default='default.jpg') + password = db.Column(db.String(60), nullable=False) + + def __repr__(self): + return f"User('{self.username}', '{self.email}', '{self.image_file}')" + +class Language(db.Model): + id = db.Column(db.Integer, primary_key=True) + language = db.Column(db.String(100), nullable=False) + + def __repr__(self): + return f"Language('{self.language}')" + +class Classes(db.Model): + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + language_id = db.Column(db.Integer, db.ForeignKey('language.id'), nullable=False) + teacher_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + start = db.Column(db.DateTime, nullable=False) + location = db.Column(db.String(120), nullable=False) + + def __repr__(self): + return f"Language('{self.id}', '{self.language_id}', '{self.start}', '{self.location}')" + + + +# date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) +# content = db.Column(db.Text, nullable=False) +# user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) diff --git a/flaskblog/routes.py b/flaskblog/routes.py @@ -0,0 +1,155 @@ +import os +import secrets + +from flask import abort, flash, redirect, render_template, request, url_for +from flask_login import current_user, login_required, login_user, logout_user +from PIL import Image + +from . import app, bcrypt, db +from .forms import LoginForm, PostForm, RegistrationForm, UpdateAccountForm +from .models import Classes, Language, User + + [email protected]("/") +def index(): + page = request.args.get('page', 1, type=int) + languages = Language.query.all() + return render_template('index.html', languages=languages) + + [email protected]("/about") +def about(): + return render_template('about.html', title='About') + + [email protected]("/register", methods=['GET', 'POST']) +def register(): + if current_user.is_authenticated: + return redirect('/') + form = RegistrationForm() + if form.validate_on_submit(): + hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8') + user = User(username=form.username.data, email=form.email.data, password=hashed_password) + db.session.add(user) + db.session.commit() + flash('Your account has been created! You are now able to log in', 'success') + return redirect(url_for('login')) + return render_template('register.html', title='Register', form=form) + + [email protected]("/login", methods=['GET', 'POST']) +def login(): + if current_user.is_authenticated: + return redirect('/') + form = LoginForm() + if form.validate_on_submit(): + user = User.query.filter_by(email=form.email.data).first() + if user and bcrypt.check_password_hash(user.password, form.password.data): + login_user(user, remember=form.remember.data) + next_page = request.args.get('next') + return redirect(next_page) if next_page else redirect('/') + else: + flash('Login Unsuccessful. Please check email and password', 'danger') + return render_template('login.html', title='Login', form=form) + + [email protected]("/logout") +def logout(): + logout_user() + return redirect('/') + + +def save_picture(form_picture): + random_hex = secrets.token_hex(8) + _, f_ext = os.path.splitext(form_picture.filename) + picture_fn = random_hex + f_ext + picturepath = os.path.join(app.root_path, 'static/profile_pics', picture_fn) + + output_size = (125, 125) + i = Image.open(form_picture) + i.thumbnail(output_size) + i.save(picturepath) + + return picture_fn + + [email protected]("/account", methods=['GET', 'POST']) +@login_required +def account(): + form = UpdateAccountForm() + if form.validate_on_submit(): + if form.picture.data: + picture_file = save_picture(form.picture.data) + current_user.image_file = picture_file + current_user.username = form.username.data + current_user.email = form.email.data + db.session.commit() + flash('Your account has been updated!', 'success') + return redirect(url_for('account')) + elif request.method == 'GET': + form.username.data = current_user.username + form.email.data = current_user.email + image_file = url_for('static', filename='profile_pics/' + current_user.image_file) + return render_template('account.html', title='Account', image_file=image_file, form=form) + + [email protected]("/post/new", methods=['GET', 'POST']) +@login_required +def new_post(): + form = PostForm() + if form.validate_on_submit(): + #post = Post(title=form.title.data, content=form.content.data, author=current_user) + db.session.add(post) + db.session.commit() + flash('Your post has been created!', 'success') + return redirect('/') + return render_template('create_post.html', title='New Post', + form=form, legend='New Post') + + [email protected]("/post/<int:post_id>") +def post(post_id): + #post = Post.query.get_or_404(post_id) + return render_template('post.html', title=post.title, post=post) + + [email protected]("/post/<int:post_id>/update", methods=['GET', 'POST']) +@login_required +def update_post(post_id): + #post = Post.query.get_or_404(post_id) + if post.author != current_user: + abort(403) + form = PostForm() + if form.validate_on_submit(): + post.title = form.title.data + post.content = form.content.data + db.session.commit() + flash('Your post has been updated!', 'success') + return redirect(url_for('post', post_id=post.id)) + elif request.method == 'GET': + form.title.data = post.title + form.content.data = post.content + return render_template('create_post.html', title='Update Post', + form=form, legend='Update Post') + + [email protected]("/post/<int:post_id>/delete", methods=['POST']) +@login_required +def delete_post(post_id): + #post = Post.query.get_or_404(post_id) + if post.author != current_user: + abort(403) + db.session.delete(post) + db.session.commit() + flash('Your post has been deleted!', 'success') + return redirect('/') + + [email protected]("/user/<string:username>") +def user_posts(username): + page = request.args.get('page', 1, type=int) + user = User.query.filter_by(username=username).first_or_404() + # posts = Post.query.filter_by(author=user)\ + # .order_by(Post.date_posted.desc())\ + # .paginate(page=page, per_page=5) + # return render_template('user_post.html', posts=posts, user=user) diff --git a/programmeerles/site.db b/flaskblog/site.db Binary files differ. diff --git a/programmeerles/static/main.css b/flaskblog/static/main.css diff --git a/programmeerles/static/profile_pics/2e32b4c96a8d8f10.jpg b/flaskblog/static/profile_pics/2e32b4c96a8d8f10.jpg Binary files differ. diff --git a/programmeerles/static/profile_pics/4895353c1045b870.jpg b/flaskblog/static/profile_pics/4895353c1045b870.jpg Binary files differ. diff --git a/programmeerles/static/profile_pics/4c4083a8362b3c0a.jpg b/flaskblog/static/profile_pics/4c4083a8362b3c0a.jpg Binary files differ. diff --git a/programmeerles/static/profile_pics/53998538edf2342c.png b/flaskblog/static/profile_pics/53998538edf2342c.png Binary files differ. diff --git a/programmeerles/static/profile_pics/6809465dffb2e5ba.jpg b/flaskblog/static/profile_pics/6809465dffb2e5ba.jpg Binary files differ. diff --git a/programmeerles/static/profile_pics/7798432669b8b3ac.jpg b/flaskblog/static/profile_pics/7798432669b8b3ac.jpg Binary files differ. diff --git a/programmeerles/static/profile_pics/85ed1b444539873d.png b/flaskblog/static/profile_pics/85ed1b444539873d.png Binary files differ. diff --git a/programmeerles/static/profile_pics/b6e1c53325f88b74.png b/flaskblog/static/profile_pics/b6e1c53325f88b74.png Binary files differ. diff --git a/programmeerles/static/profile_pics/default.jpg b/flaskblog/static/profile_pics/default.jpg Binary files differ. diff --git a/programmeerles/templates/about.html b/flaskblog/templates/about.html diff --git a/programmeerles/templates/account.html b/flaskblog/templates/account.html diff --git a/programmeerles/templates/create_post.html b/flaskblog/templates/create_post.html diff --git a/programmeerles/templates/home1.html b/flaskblog/templates/home1.html diff --git a/programmeerles/templates/index.html b/flaskblog/templates/index.html diff --git a/programmeerles/templates/layout.html b/flaskblog/templates/layout.html diff --git a/programmeerles/templates/login.html b/flaskblog/templates/login.html diff --git a/programmeerles/templates/post.html b/flaskblog/templates/post.html diff --git a/programmeerles/templates/register.html b/flaskblog/templates/register.html diff --git a/programmeerles/templates/user_post.html b/flaskblog/templates/user_post.html diff --git a/programmeerles/forms.py b/programmeerles/forms.py @@ -1,59 +0,0 @@ -from flask_wtf import FlaskForm -from flask_wtf.file import FileField, FileAllowed -from flask_login import current_user -from wtforms import StringField, PasswordField, SubmitField, BooleanField, TextAreaField -from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError -from programmeerles.models import User - - -class RegistrationForm(FlaskForm): - username = StringField('Username', - validators=[DataRequired(), Length(min=2, max=20)]) - email = StringField('Email', - validators=[DataRequired(), Email()]) - password = PasswordField('Password', validators=[DataRequired()]) - confirm_password = PasswordField('Confirm Password', - validators=[DataRequired(), EqualTo('password')]) - submit = SubmitField('Sign Up') - - def validate_username(self, username): - user = User.query.filter_by(username=username.data).first() - if user: - raise ValidationError('That username is taken. Please choose a different one.') - - def validate_email(self, email): - user = User.query.filter_by(email=email.data).first() - if user: - raise ValidationError('That email is taken. Please choose a different one.') - - -class LoginForm(FlaskForm): - email = StringField('Email', - validators=[DataRequired(), Email()]) - password = PasswordField('Password', validators=[DataRequired()]) - remember = BooleanField('Remember Me') - submit = SubmitField('Login') - -class UpdateAccountForm(FlaskForm): - username = StringField('Username', - validators=[DataRequired(), Length(min=2, max=20)]) - email = StringField('Email', - validators=[DataRequired(), Email()]) - picture = FileField('Update Profile Picture',validators=[FileAllowed(['jpg','png'])]) - submit = SubmitField('Update') - - def validate_username(self, username): - if username.data != current_user.username: - user = User.query.filter_by(username=username.data).first() - if user: - raise ValidationError('That username is taken. Please choose a different one.') - - def validate_email(self, email): - if email.data != current_user.email: - user = User.query.filter_by(email=email.data).first() - if user: - raise ValidationError('That email is taken. Please choose a different one.') -class PostForm(FlaskForm): - title = StringField('Title', validators=[DataRequired()]) - content = TextAreaField('Content', validators=[DataRequired()]) - submit = SubmitField('Post') -\ No newline at end of file diff --git a/programmeerles/models.py b/programmeerles/models.py @@ -1,43 +0,0 @@ -from datetime import datetime -from programmeerles import db, login_manager -from flask_login import UserMixin - - -@login_manager.user_loader -def load_user(user_id): - return User.query.get(int(user_id)) - - -class User(db.Model, UserMixin): - id = db.Column(db.Integer, primary_key=True) - username = db.Column(db.String(20), unique=True, nullable=False) - email = db.Column(db.String(120), unique=True, nullable=False) - image_file = db.Column(db.String(20), nullable=False, default='default.jpg') - password = db.Column(db.String(60), nullable=False) - - def __repr__(self): - return f"User('{self.username}', '{self.email}', '{self.image_file}')" - -class Language(db.Model): - id = db.Column(db.Integer, primary_key=True) - language = db.Column(db.String(100), nullable=False) - - def __repr__(self): - return f"Language('{self.language}')" - -class Classes(db.Model): - id = db.Column(db.Integer, primary_key=True) - user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) - language_id = db.Column(db.Integer, db.ForeignKey('language.id'), nullable=False) - teacher_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) - start = db.Column(db.DateTime, nullable=False) - location = db.Column(db.String(120), nullable=False) - - def __repr__(self): - return f"Language('{self.id}', '{self.language_id}', '{self.start}', '{self.location}')" - - - -# date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) -# content = db.Column(db.Text, nullable=False) -# user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) diff --git a/programmeerles/routes.py b/programmeerles/routes.py @@ -1,149 +0,0 @@ -import os -import secrets - -from flask import abort, flash, redirect, render_template, request, url_for -from flask_login import current_user, login_required, login_user, logout_user -from PIL import Image - -from programmeerles import app, bcrypt, db -from programmeerles.forms import (LoginForm, PostForm, RegistrationForm, - UpdateAccountForm) -from programmeerles.models import Classes, Language, User - - [email protected]("/") -def index(): - page = request.args.get('page', 1, type=int) - languages = Language.query.all() - return render_template('index.html', languages=languages) - - [email protected]("/about") -def about(): - return render_template('about.html', title='About') - - [email protected]("/register", methods=['GET', 'POST']) -def register(): - if current_user.is_authenticated: - return redirect('/') - form = RegistrationForm() - if form.validate_on_submit(): - hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8') - user = User(username=form.username.data, email=form.email.data, password=hashed_password) - db.session.add(user) - db.session.commit() - flash('Your account has been created! You are now able to log in', 'success') - return redirect(url_for('login')) - return render_template('register.html', title='Register', form=form) - - [email protected]("/login", methods=['GET', 'POST']) -def login(): - if current_user.is_authenticated: - return redirect('/') - form = LoginForm() - if form.validate_on_submit(): - user = User.query.filter_by(email=form.email.data).first() - if user and bcrypt.check_password_hash(user.password, form.password.data): - login_user(user, remember=form.remember.data) - next_page = request.args.get('next') - return redirect(next_page) if next_page else redirect('/') - else: - flash('Login Unsuccessful. Please check email and password', 'danger') - return render_template('login.html', title='Login', form=form) - - [email protected]("/logout") -def logout(): - logout_user() - return redirect('/') - -def save_picture(form_picture): - random_hex = secrets.token_hex(8) - _, f_ext = os.path.splitext(form_picture.filename) - picture_fn = random_hex + f_ext - picturepath = os.path.join(app.root_path, 'static/profile_pics', picture_fn) - - output_size = (125, 125) - i = Image.open(form_picture) - i.thumbnail(output_size) - i.save(picturepath) - - return picture_fn - [email protected]("/account", methods=['GET', 'POST']) -@login_required -def account(): - form = UpdateAccountForm() - if form.validate_on_submit(): - if form.picture.data: - picture_file = save_picture(form.picture.data) - current_user.image_file = picture_file - current_user.username = form.username.data - current_user.email = form.email.data - db.session.commit() - flash('Your account has been updated!', 'success') - return redirect(url_for('account')) - elif request.method == 'GET': - form.username.data = current_user.username - form.email.data = current_user.email - image_file = url_for('static', filename='profile_pics/' + current_user.image_file) - return render_template('account.html', title='Account', image_file=image_file, form=form) - [email protected]("/post/new", methods=['GET', 'POST']) -@login_required -def new_post(): - form = PostForm() - if form.validate_on_submit(): - #post = Post(title=form.title.data, content=form.content.data, author=current_user) - db.session.add(post) - db.session.commit() - flash('Your post has been created!', 'success') - return redirect('/') - return render_template('create_post.html', title='New Post', - form=form, legend='New Post') - [email protected]("/post/<int:post_id>") -def post(post_id): - #post = Post.query.get_or_404(post_id) - return render_template('post.html', title=post.title, post=post) - [email protected]("/post/<int:post_id>/update", methods=['GET', 'POST']) -@login_required -def update_post(post_id): - #post = Post.query.get_or_404(post_id) - if post.author != current_user: - abort(403) - form = PostForm() - if form.validate_on_submit(): - post.title = form.title.data - post.content = form.content.data - db.session.commit() - flash('Your post has been updated!', 'success') - return redirect(url_for('post', post_id=post.id)) - elif request.method == 'GET': - form.title.data = post.title - form.content.data = post.content - return render_template('create_post.html', title='Update Post', - form=form, legend='Update Post') - [email protected]("/post/<int:post_id>/delete", methods=['POST']) -@login_required -def delete_post(post_id): - #post = Post.query.get_or_404(post_id) - if post.author != current_user: - abort(403) - db.session.delete(post) - db.session.commit() - flash('Your post has been deleted!', 'success') - return redirect('/') - [email protected]("/user/<string:username>") -def user_posts(username): - page = request.args.get('page', 1, type=int) - user = User.query.filter_by(username=username).first_or_404() - #posts = Post.query.filter_by(author=user)\ - # .order_by(Post.date_posted.desc())\ - #.paginate(page=page, per_page=5) - #return render_template('user_post.html', posts=posts, user=user) diff --git a/run.py b/run.py @@ -1,4 +1,4 @@ -from programmeerles import app +from flaskblog import app if __name__ == '__main__': app.run(debug=True)