Implemented bluorints for flask

master
key 2 years ago
parent 23aa5d8cee
commit 0f0f148418

@ -3,23 +3,40 @@ from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
from flask_mail import Mail
import os
from minibase.config import Config
app = Flask(__name__)
app.config['SECRET_KEY'] = '5791628bb0b13ce0c676dfde280ba245'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
# (DATABASE) Definition
db = SQLAlchemy()
# (PASSWORD) Hashign Program to save paswords safely
bcrypt = Bcrypt()
# (LOGIN) Login manage plugin configuration
login_manager = LoginManager()
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'
login_manager.login_message_category = 'info' #Boostrap Info Message
app.config['MAIL_SERVER']= 'smtp.googlemail.com'
app.config['MAIL_PORT']= 465
app.config['MAIL_USE_TLS']= False
app.config['MAIL_USE_SSL']= True
app.config['MAIL_USERNAME']= 'kerem.yollu@gmail.com'
app.config['MAIL_PASSWORD']= 'eoilsjxjwmnfjbbj'
mail = Mail(app)
# (EMAIL AGENT) Definition
mail = Mail()
from minibase import route
def create_minibase(config_class=Config):
# (FLASK) Main Flask Application
app = Flask(__name__)
app.config.from_object(Config)
# (DATABASE) Initialisation
db.init_app(app)
# (PASSWORD) Initialisation
bcrypt.init_app(app)
# (LOGIN) Initialisation
login_manager.init_app(app)
# (EMAIL AGENT) Initialisation
mail.init_app(app)
# (FLASK) Importing adn then registering blueprints
from minibase.users.routes import users
from minibase.posts.routes import posts
from minibase.main.routes import main
app.register_blueprint(users)
app.register_blueprint(posts)
app.register_blueprint(main)
# Retunr The ccreated app
return app

@ -0,0 +1,16 @@
import os
class Config:
# (FLASK) Sectret key wich will be used to secure some requests an connections
SECRET_KEY = os.environ.get('MINIBASE_SECRET_KEY')
# (SQLALCHEMY) COnfiguration
SQLALCHEMY_DATABASE_URI = os.environ.get('MINIBASE_SQLALCHEMY_DATABASE_URI')
# (MAIL AGENT) Configure mail Server to send EMails.
MAIL_SERVER = os.environ.get('MINIBASE_MAIL_SERVER')
MAIL_USERNAME = os.environ.get('MINIBASE_MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MINIBASE_MAIL_PASSWORD')
MAIL_PORT = 465
MAIL_USE_TLS = False
MAIL_USE_SSL = True

@ -0,0 +1,21 @@
from flask import render_template, request, Blueprint
from minibase.models import Post
# Declaring a blueprint
main = Blueprint('main', __name__)
#Redirect from / and also /home routes to the /
@main.route("/")
@main.route("/home")
def home():
# (PAGINATION) Defines the page number that we will start with
page = request.args.get('page', 1, type=int)
# (POSTS) Query posts usin SQLAlchemy
posts = Post.query.order_by(Post.date_posted.asc()).paginate(per_page=2)
# (HTML) Renders the template for templates/home.html
return render_template('home.html', posts=posts)
@main.route("/about")
def about():
return render_template('about.html', title='About')

@ -1,7 +1,9 @@
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from datetime import datetime
from minibase import db, login_manager, app
from minibase import db, login_manager
from flask_login import UserMixin
from flask import url_for, current_app
@login_manager.user_loader
@ -17,12 +19,12 @@ class User(db.Model, UserMixin):
posts = db.relationship('Post', backref='author', lazy=True)
def get_reset_token(self, expires_sec=1800):
s = Serializer(app.config['SECRET_KEY'], expires_sec)
s = Serializer(current_app.config['SECRET_KEY'], expires_sec)
return s.dumps({'user_id': self.id}).decode('utf-8')
@staticmethod
def verify_reset_token(token):
s = Serializer(app.config['SECRET_KEY'])
s = Serializer(current_app.config['SECRET_KEY'])
try:
user_id = s.loads(token)['user_id']
except:

@ -0,0 +1,10 @@
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField
from wtforms.validators import DataRequired
class postForm(FlaskForm):
title = StringField('Title',
validators=[DataRequired()])
content = TextAreaField('Content',
validators=[DataRequired()])
submit = SubmitField('Post')

@ -0,0 +1,55 @@
from flask import (render_template, url_for, flash,
redirect, request, abort, Blueprint)
from flask_login import current_user, login_required
from minibase import db
from minibase.models import Post
from minibase.posts.forms import postForm
# Declaring a blueprint
posts = Blueprint('posts', __name__)
@posts.route("/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(url_for('main.home'))
return render_template('create_post.html', title='Create Post', legend='Create Post', form=form)
@posts.route("/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)
@posts.route("/post/<int:post_id>/update", methods=['GET', 'POST'])
@login_required
def post_update(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('posts.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', legend='Update Post', form=form)
@posts.route("/post/<int:post_id>/delete", methods=['POST'])
@login_required
def post_delete(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(url_for('main.home'))

@ -1,183 +0,0 @@
import os
import secrets
from PIL import Image
from flask import render_template, url_for, flash, redirect, request, abort
from minibase import app, db, bcrypt, mail
from minibase.forms import registrationForm, loginForm, updateAccountForm, postForm, requestResetForm, resetPasswordForm
from minibase.models import User, Post
from flask_login import login_user, current_user, logout_user, login_required
from flask_mail import Message
#Redirect from / and also /home routes to the /
@app.route("/")
@app.route("/home")
def home():
page = request.args.get('page', 1, type=int)
posts = Post.query.order_by(Post.date_posted.asc()).paginate(per_page=2)
return render_template('home.html', posts=posts)
@app.route("/about")
def about():
return render_template('about.html', title='About')
@app.route("/register", methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = registrationForm()
if form.validate_on_submit():
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user = User(username=form.username.data, email=form.email.data, password=hashed_pw)
db.session.add(user)
db.session.commit()
flash(f'Your account has benn created you can now log in!','success')
return redirect(url_for('login'))
return render_template('register.html', title='Register', form=form)
@app.route("/login", methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('home'))
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(url_for('home'))
else:
flash('Login unsuccessful. Please chek your Email and Password!','danger')
return render_template('login.html', title='Login', form=form)
@app.route("/logout")
def logout():
logout_user()
return redirect(url_for('home'))
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
picture_path = os.path.join(app.root_path, 'static/pics', picture_fn)
output_size = (125,125)
i = Image.open(form_picture)
i.thumbnail(output_size)
i.save(picture_path)
return picture_fn
@app.route("/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='pics/'+ current_user.image_file)
return render_template('account.html', title='Account', image_file = image_file, form=form)
@app.route("/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(url_for('home'))
return render_template('create_post.html', title='Create Post', legend='Create Post', form=form)
@app.route("/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)
@app.route("/post/<int:post_id>/update", methods=['GET', 'POST'])
@login_required
def post_update(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', legend='Update Post', form=form)
@app.route("/post/<int:post_id>/delete", methods=['POST'])
@login_required
def post_delete(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(url_for('home'))
@app.route("/user/<string:username>")
def user_posts(username):
user = User.query.filter_by(username=username).first_or_404()
page = request.args.get('page', 1, type=int)
posts = Post.query.filter_by(author=user)\
.order_by(Post.date_posted.asc())\
.paginate(page=page, per_page=2)
return render_template('user_posts.html', posts=posts, user=user)
def send_reset_email(user):
token = user.get_reset_token()
msg = Message('Password Reset Request',
sender='noreply@demo.com',
recipients=[user.email])
msg.body = f'''To reset your password, visit the following link:
{url_for('reset_token', token=token, _external=True)}
If you didn't make this request, then simply ingnore this email and no chancges will be made.
'''
mail.send(msg)
@app.route("/reset_password", methods=['GET', 'POST'])
def reset_request():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = requestResetForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
send_reset_email(user)
flash('An Email has benn sent with instruction to reset your password', 'warning')
return render_template('reset_request.html', title='Reset Password', form=form)
@app.route("/reset_password/<token>", methods=['GET', 'POST'])
def reset_token(token):
if current_user.is_authenticated:
return redirect(url_for('home'))
user = User.verify_reset_token(token)
if user is None:
flash('That is an invalid or expired token', 'warning')
return redirect(url_for('reset_request'))
form = resetPasswordForm()
if form.validate_on_submit():
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user.password = hashed_pw
db.session.commit()
flash(f'Your password has benn udated','success')
return redirect(url_for('login'))
return render_template('reset_token.html', title='Reset Password', form=form)

Binary file not shown.

@ -6,10 +6,10 @@
<img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{{ url_for('user_posts', username=post.author.username) }} ">{{ post.author.username }}</a>
<a class="mr-2" href="{{ url_for('users.user_posts', username=post.author.username) }} ">{{ post.author.username }}</a>
<small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small>
</div>
<h2><a class="article-title" href="{{ url_for('post', post_id=post.id) }}">{{ post.title }}</a></h2>
<h2><a class="article-title" href="{{ url_for('posts.post', post_id=post.id) }}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
@ -17,9 +17,9 @@
{% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %}
{% if page_num %}
{% if posts.page == page_num %}
<a class="btn btn-info mb-4" href="{{ url_for('home', page=page_num) }}">{{ page_num }}</a>
<a class="btn btn-info mb-4" href="{{ url_for('main.home', page=page_num) }}">{{ page_num }}</a>
{% else %}
<a class="btn btn-outline-info mb-4" href="{{ url_for('home', page=page_num) }}">{{ page_num }}</a>
<a class="btn btn-outline-info mb-4" href="{{ url_for('main.home', page=page_num) }}">{{ page_num }}</a>
{% endif %}
{% else %}
...

@ -17,24 +17,24 @@
<header class="site-header">
<nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
<div class="container">
<a class="navbar-brand mr-4" href="{{ url_for('home') }}">MiniBase</a>
<a class="navbar-brand mr-4" href="{{ url_for('main.home') }}">MiniBase</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarToggle">
<div class="navbar-nav mr-auto">
<a class="nav-item nav-link" href="{{ url_for('home') }}">Home</a>
<a class="nav-item nav-link" href="{{ url_for('about') }}">About</a>
<a class="nav-item nav-link" href="{{ url_for('main.home') }}">Home</a>
<a class="nav-item nav-link" href="{{ url_for('main.about') }}">About</a>
</div>
<!-- Navbar Right Side -->
<div class="navbar-nav">
{% if current_user.is_authenticated %}
<a class="nav-item nav-link" href="{{ url_for('new_post') }}">New Post</a>
<a class="nav-item nav-link" href="{{ url_for('logout') }}">Logout</a>
<a class="nav-item nav-link" href="{{ url_for('account') }}">Account</a>
<a class="nav-item nav-link" href="{{ url_for('posts.new_post') }}">New Post</a>
<a class="nav-item nav-link" href="{{ url_for('users.logout') }}">Logout</a>
<a class="nav-item nav-link" href="{{ url_for('users.account') }}">Account</a>
{% else %}
<a class="nav-item nav-link" href="{{ url_for('login') }}">Login</a>
<a class="nav-item nav-link" href="{{ url_for('register') }}">Register</a>
<a class="nav-item nav-link" href="{{ url_for('users.login') }}">Login</a>
<a class="nav-item nav-link" href="{{ url_for('users.register') }}">Register</a>
{% endif %}
</div>
</div>

@ -40,13 +40,13 @@
{{ form.submit(class="btn btn-outline-info") }}
</div>
<small class="text-muted ml-2">
<a href="{{ url_for('reset_request') }}">Forgot Password?</a>
<a href="{{ url_for('users.reset_request') }}">Forgot Password?</a>
</small>
</form>
</div>
<div class="border-top pt-3">
<small class="text-muted">
Need An Account? <a class="ml-2" href="{{ url_for('register') }}">Sign Up Now</a>
Need An Account? <a class="ml-2" href="{{ url_for('users.register') }}">Sign Up Now</a>
</small>
</div>
{% endblock content %}

@ -5,11 +5,11 @@
<img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{{ url_for('user_posts', username=post.author.username) }}" >{{ post.author.username }}</a>
<a class="mr-2" href="{{ url_for('users.user_posts', username=post.author.username) }}" >{{ post.author.username }}</a>
<small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small>
{% if post.author == current_user %}
<div>
<a class="btn btn-secondary btn-sm m-1" href="{{ url_for('post_update', post_id=post.id) }}">Update</a>
<a class="btn btn-secondary btn-sm m-1" href="{{ url_for('posts.post_update', post_id=post.id) }}">Update</a>
<button type="button" class="btn btn-danger btn-sm m-1" data-bs-toggle="modal" data-bs-target="#staticBackdrop">Delete</button>
</div>
{% endif %}
@ -31,7 +31,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<form action="{{ url_for('post_delete', post_id=post.id) }}" method="POST">
<form action="{{ url_for('posts.post_delete', post_id=post.id) }}" method="POST">
<input class="btn btn-danger" type="submit" value="Delete">
</div>
</div>

@ -66,7 +66,7 @@
</div>
<div class="border-top pt-3">
<small class="text-muted">
Already Have An Account? <a class="ml-2" href="{{ url_for('login') }}">Sign In</a>
Already Have An Account? <a class="ml-2" href="{{ url_for('users.login') }}">Sign In</a>
</small>
</div>
{% endblock content %}

@ -7,10 +7,10 @@
<img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{{ url_for('user_posts', username=post.author.username) }} ">{{ post.author.username }}</a>
<a class="mr-2" href="{{ url_for('users.user_posts', username=post.author.username) }} ">{{ post.author.username }}</a>
<small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small>
</div>
<h2><a class="article-title" href="{{ url_for('post', post_id=post.id) }}">{{ post.title }}</a></h2>
<h2><a class="article-title" href="{{ url_for('posts.post', post_id=post.id) }}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
@ -18,9 +18,9 @@
{% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %}
{% if page_num %}
{% if posts.page == page_num %}
<a class="btn btn-info mb-4" href="{{ url_for('user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a>
<a class="btn btn-info mb-4" href="{{ url_for('users.user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a>
{% else %}
<a class="btn btn-outline-info mb-4" href="{{ url_for('user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a>
<a class="btn btn-outline-info mb-4" href="{{ url_for('users.user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a>
{% endif %}
{% else %}
...

@ -1,8 +1,8 @@
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 import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from flask_login import current_user
from minibase.models import User
class registrationForm(FlaskForm):
@ -55,13 +55,6 @@ class updateAccountForm(FlaskForm):
if email:
raise ValidationError('That email is taken do you have an acocunt ?')
class postForm(FlaskForm):
title = StringField('Title',
validators=[DataRequired(),Length(min = 3, max = 100)])
content = TextAreaField('Content',
validators=[DataRequired()])
submit = SubmitField('Post')
class requestResetForm(FlaskForm):
email = StringField('Email',
validators=[DataRequired(),Email()])

@ -0,0 +1,106 @@
from flask import render_template, url_for, flash, redirect, request, Blueprint
from flask_login import login_user, current_user, logout_user, login_required
from minibase import db, bcrypt
from minibase.models import User, Post
from minibase.users.forms import registrationForm, loginForm, updateAccountForm, requestResetForm, resetPasswordForm
from minibase.posts.forms import postForm
from minibase.users.utils import save_picture, send_reset_email
# Declaring a blueprint
users = Blueprint('users', __name__)
#Route is the file that is going to be generated
@users.route("/register", methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('main.home'))
form = registrationForm()
if form.validate_on_submit():
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user = User(username=form.username.data, email=form.email.data, password=hashed_pw)
db.session.add(user)
db.session.commit()
flash(f'Your account has benn created you can now log in!','success')
return redirect(url_for('users.login'))
return render_template('register.html', title='Register', form=form)
@users.route("/login", methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('main.home'))
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(url_for('main.home'))
else:
flash('Login unsuccessful. Please chek your Email and Password!','danger')
return render_template('login.html', title='Login', form=form)
@users.route("/logout")
def logout():
logout_user()
return redirect(url_for('main.home'))
@users.route("/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('users.account'))
elif request.method == 'GET':
form.username.data = current_user.username
form.email.data = current_user.email
image_file = url_for('static', filename='pics/'+ current_user.image_file)
return render_template('account.html', title='Account', image_file = image_file, form=form)
@users.route("/user/<string:username>")
def user_posts(username):
user = User.query.filter_by(username=username).first_or_404()
page = request.args.get('page', 1, type=int)
posts = Post.query.filter_by(author=user)\
.order_by(Post.date_posted.asc())\
.paginate(page=page, per_page=2)
return render_template('user_posts.html', posts=posts, user=user)
@users.route("/reset_password", methods=['GET', 'POST'])
def reset_request():
if current_user.is_authenticated:
return redirect(url_for('main.home'))
form = requestResetForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
send_reset_email(user)
flash('An Email has benn sent with instruction to reset your password', 'warning')
return render_template('reset_request.html', title='Reset Password', form=form)
@users.route("/reset_password/<token>", methods=['GET', 'POST'])
def reset_token(token):
if current_user.is_authenticated:
return redirect(url_for('main.home'))
user = User.verify_reset_token(token)
if user is None:
flash('That is an invalid or expired token', 'warning')
return redirect(url_for('users.reset_request'))
form = resetPasswordForm()
if form.validate_on_submit():
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user.password = hashed_pw
db.session.commit()
flash(f'Your password has benn udated','success')
return redirect(url_for('users.login'))
return render_template('reset_token.html', title='Reset Password', form=form)

@ -0,0 +1,28 @@
import os
import secrets
from PIL import Image
from flask import url_for, current_app
from flask_mail import Message
from minibase import mail
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
picture_path = os.path.join(current_app.root_path, 'static/pics', picture_fn)
output_size = (125,125)
i = Image.open(form_picture)
i.thumbnail(output_size)
i.save(picture_path)
return picture_fn
def send_reset_email(user):
token = user.get_reset_token()
msg = Message('Password Reset Request',
sender='noreply@demo.com',
recipients=[user.email])
msg.body = f'''To reset your password, visit the following link:
{url_for('reset_token', token=token, _external=True)}
If you didn't make this request, then simply ingnore this email and no chancges will be made.
'''
mail.send(msg)
Loading…
Cancel
Save