Revamp all model relationships to use backref attributes properly

- Fix new post form not including a CSRF token
- Removed some old leftover comment profanity validation, changed to validate_on_submit() for first time
- Include rest of pluralize macro work with this commit + used pluralizing logic where there once was none
This commit is contained in:
Xevion
2022-03-29 18:12:07 -05:00
parent db560b7c41
commit fd35443a9a
8 changed files with 47 additions and 52 deletions

4
app.py
View File

@@ -109,7 +109,7 @@ def create_app():
post_count: int = 0 post_count: int = 0
for author in random.choices(all_users, k=count // 2): for author in random.choices(all_users, k=count // 2):
new_post = Post(author=author.id, text=fake.paragraph(nb_sentences=2)) new_post = Post(author=author, text=fake.paragraph(nb_sentences=2))
db.session.add(new_post) db.session.add(new_post)
post_count += 1 post_count += 1
@@ -119,7 +119,7 @@ def create_app():
comment_count: int = 0 comment_count: int = 0
for post in Post.query.all(): for post in Post.query.all():
for _ in range(random.randint(3, len(all_users) // 4)): for _ in range(random.randint(3, len(all_users) // 4)):
new_comment = Comment(text=fake.paragraph(nb_sentences=1), author=random.choice(all_users).id, post=post.id) new_comment = Comment(text=fake.paragraph(nb_sentences=1), author=random.choice(all_users), post=post)
db.session.add(new_comment) db.session.add(new_comment)
comment_count += 1 comment_count += 1

View File

@@ -14,7 +14,7 @@ def edit_profile_post(username: str):
form = EditProfileForm(request.form) form = EditProfileForm(request.form)
user = User.query.filter_by(username=username).first_or_404() user = User.query.filter_by(username=username).first_or_404()
if current_user.is_admin or user.id == current_user.id: if current_user.is_admin or user == current_user:
if form.validate(): if form.validate():
user.about_me = form.about_me.data user.about_me = form.about_me.data
db.session.commit() db.session.commit()
@@ -24,6 +24,9 @@ def edit_profile_post(username: str):
@blueprint.route('/login', methods=['GET', 'POST']) @blueprint.route('/login', methods=['GET', 'POST'])
def login(): def login():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = LoginForm(request.form) form = LoginForm(request.form)
if request.method == 'POST' and form.validate(): if request.method == 'POST' and form.validate():
@@ -44,7 +47,9 @@ def login():
@blueprint.route('/signup', methods=['GET', 'POST']) @blueprint.route('/signup', methods=['GET', 'POST'])
def signup(): def signup():
# validate and add user to db if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = RegistrationForm(request.form) form = RegistrationForm(request.form)
if request.method == 'POST' and form.validate(): if request.method == 'POST' and form.validate():

View File

@@ -21,8 +21,8 @@ class User(UserMixin, db.Model):
last_seen = db.Column(db.DateTime, nullable=False, server_default=func.now()) last_seen = db.Column(db.DateTime, nullable=False, server_default=func.now())
last_ip = db.Column(db.String(64), nullable=True) last_ip = db.Column(db.String(64), nullable=True)
is_admin = db.Column(db.Boolean, default=False) is_admin = db.Column(db.Boolean, default=False)
posts = db.relationship("Post") posts = db.relationship("Post", backref='author')
comments = db.relationship("Comment") comments = db.relationship("Comment", backref='author')
def get_last_seen(self) -> str: def get_last_seen(self) -> str:
delta: datetime.timedelta = datetime.datetime.utcnow() - self.last_seen delta: datetime.timedelta = datetime.datetime.utcnow() - self.last_seen
@@ -40,14 +40,15 @@ class User(UserMixin, db.Model):
def display_about(self) -> str: def display_about(self) -> str:
return self.about_me or "This user hasn't written a bio yet." return self.about_me or "This user hasn't written a bio yet."
class Post(db.Model): class Post(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
author = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) author_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
text = db.Column(db.Text) text = db.Column(db.Text)
date_posted = db.Column(db.DateTime, server_default=func.now()) date_posted = db.Column(db.DateTime, server_default=func.now())
date_updated = db.Column(db.DateTime, nullable=True) date_updated = db.Column(db.DateTime, nullable=True)
likes = db.Column(db.Text, default='[]') likes = db.Column(db.Text, default='[]')
comments = db.relationship("Comment") comments = db.relationship("Comment", backref='post')
def get_likes(self) -> List[int]: def get_likes(self) -> List[int]:
"""Return the IDs of the Users who have liked this post.""" """Return the IDs of the Users who have liked this post."""
@@ -72,6 +73,6 @@ class Post(db.Model):
class Comment(db.Model): class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.Text, nullable=False) text = db.Column(db.Text, nullable=False)
author = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
post = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False) post_id = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False)
date_posted = db.Column(db.DateTime, server_default=func.now()) date_posted = db.Column(db.DateTime, server_default=func.now())

View File

@@ -1,4 +1,4 @@
from flask import Blueprint, flash, redirect, request, url_for from flask import Blueprint, flash, redirect, request, url_for, render_template
from flask_login import current_user, login_required from flask_login import current_user, login_required
from profanity_filter import ProfanityFilter from profanity_filter import ProfanityFilter
from forms import RegistrationForm, EditProfileForm, NewPostForm, NewCommentForm from forms import RegistrationForm, EditProfileForm, NewPostForm, NewCommentForm
@@ -15,7 +15,7 @@ def edit_profile_post(username):
user = db.session.query(User).filter_by(username=username).first_or_404() user = db.session.query(User).filter_by(username=username).first_or_404()
# Allow admins to edit profiles, but deny other users # Allow admins to edit profiles, but deny other users
if not current_user.is_admin and current_user.id != user.id: if not current_user.is_admin and current_user != user:
return redirect(url_for('main.view_user', username=username)) return redirect(url_for('main.view_user', username=username))
form = RegistrationForm(request.form) form = RegistrationForm(request.form)
@@ -34,13 +34,11 @@ def add_comment(post_id: int):
post = Post.query.get_or_404(post_id) post = Post.query.get_or_404(post_id)
form = NewCommentForm(request.form) form = NewCommentForm(request.form)
if form.validate(): if form.validate_on_submit():
if not pf.is_clean(form.text.data): comment = Comment(post=post, author=current_user, text=form.text.data)
flash('Sorry, profanity is not allowed on runnerspace.')
return redirect(url_for('main.view_post', post_id=post_id))
comment = Comment(post=post.id, author=current_user.id, text=form.text.data)
db.session.add(comment) db.session.add(comment)
db.session.commit() db.session.commit()
return redirect(url_for('main.view_post', post_id=post.id)) return redirect(url_for('main.view_post', post_id=post.id))
return render_template('pages/post.html', form=form, post=post)

View File

@@ -2,7 +2,7 @@ from flask import Blueprint, redirect, render_template, url_for, request
from flask_login import current_user, login_required from flask_login import current_user, login_required
from models import User, Post, Comment from models import User, Post, Comment
from forms import NewPostForm, EditProfileForm from forms import NewPostForm, NewCommentForm, EditProfileForm
from database import db from database import db
blueprint = Blueprint('main', __name__) blueprint = Blueprint('main', __name__)
@@ -32,27 +32,23 @@ def browse():
@blueprint.route('/feed', methods=['GET', 'POST']) @blueprint.route('/feed', methods=['GET', 'POST'])
def feed(): def feed():
posts = Post.query.all() posts = Post.query.order_by(Post.date_posted.desc()).all()
authors = [User.query.get_or_404(post.author) for post in posts]
form = NewPostForm(request.form) form = NewPostForm(request.form)
if request.method == 'POST' and form.validate(): if request.method == 'POST' and form.validate():
post = Post(author=current_user.id, text=form.text.data) post = Post(author=current_user, text=form.text.data)
db.session.add(post) db.session.add(post)
db.session.commit() db.session.commit()
return redirect(url_for('main.view_post', post_id=post.id)) return redirect(url_for('main.view_post', post_id=post.id))
return render_template('pages/feed.html', posts_and_authors=zip(posts, authors), form=form) return render_template('pages/feed.html', posts=posts, form=form)
@blueprint.route('/feed/<post_id>') @blueprint.route('/feed/<post_id>')
def view_post(post_id: int): def view_post(post_id: int):
post = Post.query.get_or_404(post_id) post = Post.query.get_or_404(post_id)
comments = post.comments return render_template('pages/post.html', form=NewCommentForm(), post=post)
comment_authors = [User.query.get_or_404(comment.author) for comment in comments]
return render_template('pages/post.html', post=post, author=User.query.get_or_404(post.author),
comments_and_authors=zip(comments, comment_authors))
# @blueprint.route('/messages') # @blueprint.route('/messages')
@@ -79,7 +75,7 @@ def edit_user(username: str):
if request.method == 'POST': if request.method == 'POST':
if form.validate(): if form.validate():
if current_user.is_admin or current_user.id == user.id: if current_user.is_admin or current_user == user:
user.about_me = form.about_me.data user.about_me = form.about_me.data
user.name = form.name.data user.name = form.name.data

View File

@@ -4,6 +4,7 @@
{% block content %} {% block content %}
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
<form method="POST" class="form post-form"> <form method="POST" class="form post-form">
{{ form.csrf_token }}
{{ render_field(form.text, show_label=False) }} {{ render_field(form.text, show_label=False) }}
<input type=submit value="Create Post"> <input type=submit value="Create Post">
</form> </form>
@@ -11,13 +12,15 @@
<hr style="margin: 2em 0"> <hr style="margin: 2em 0">
{% for post, author in posts_and_authors %} {% for post in posts %}
<div class="post-box"> <div class="post-box">
{{ post.text }} {{ post.text }}
<div class="post-author no-border"> <div class="post-author no-border">
<em>Posted by <a href="{{ url_for('main.view_user', username=author.username) }}">{{ author.name }}</a></em> <span {% with comment_count = post.comments|length %}
title="{{ post.date_posted }}">{{ post.get_time_ago() }} ago</span>. | <em>Posted by <a href="{{ url_for('main.view_user', username=post.author.username) }}">{{ post.author.name }}</a></em>
<a href="{{ url_for('main.view_post', post_id=post.id) }}"><span>{{ post.comments|length }} comments</span></a> <span title="{{ post.date_posted }}">{{ post.get_time_ago() }} ago</span>. |
<a href="{{ url_for('main.view_post', post_id=post.id) }}"><span> {{ comment_count }} comment{{ comment_count|pluralize }}</span></a>
{% endwith %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}

View File

@@ -4,33 +4,25 @@
{{ post.text }} {{ post.text }}
<br> <br>
<div class="post-author"> <div class="post-author">
<em>Posted by <a href="{{ url_for('main.view_user', username=author.username) }}">{{ author.name }}</a></em> <span <em>Posted by <a href="{{ url_for('main.view_user', username=post.author.username) }}">{{ post.author.name }}</a></em> <span
title="{{ post.date_posted }}">{{ post.get_time_ago() }} ago</span>. title="{{ post.date_posted }}">{{ post.get_time_ago() }} ago</span>.
</div> </div>
<div class="post-comments"> <div class="post-comments">
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
{% with messages = get_flashed_messages() %}
{% if messages %}
<span class="error-message">
{{ messages[0] }}
</span>
{% endif %}
{% endwith %}
<div class="post-comment add-comment"> <div class="post-comment add-comment">
<form method="POST" action="{{ url_for('forms.add_comment', post_id=post.id) }}"> <form method="POST" action="{{ url_for('forms.add_comment', post_id=post.id) }}">
<label> {{ form.csrf_token }}
<input type="text" name="comment-text"> {{ form.text }}
</label> <input type=submit value="Add Comment">
<button>Add Comment</button>
</form> </form>
</div> </div>
{% endif %} {% endif %}
{% for comment, author in comments_and_authors %} {% for comment in post.comments %}
<div class="post-comment"> <div class="post-comment">
<span class="comment-text">"{{ comment.text }}"</span>
<span class="comment-text">"{{ comment.text }}"</span><a class="comment-author" <a class="comment-author"
href="{{ url_for('main.view_user', username=author.username) }}">{{ author.name }}</a> href="{{ url_for('main.view_user', username=comment.author) }}">{{ comment.author.name }}
</a>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>

View File

@@ -3,7 +3,7 @@
{% block content %} {% block content %}
<div class="profile-title"> <div class="profile-title">
<span class="profile-username">{{ user.name }}</span> <span class="profile-username">{{ user.name }}</span>
{% if current_user.is_admin or current_user.id == user.id %} {% if current_user.is_admin or current_user == user %}
<a href="{{ url_for('main.edit_user', username=current_user.username) }}"><i class="fas fa-pencil-alt fa-sm" style="padding-bottom: 3px; padding-left: 0.5em;"></i></a> <a href="{{ url_for('main.edit_user', username=current_user.username) }}"><i class="fas fa-pencil-alt fa-sm" style="padding-bottom: 3px; padding-left: 0.5em;"></i></a>
{% endif %} {% endif %}
{% with seen_text = user.get_last_seen() %} {% with seen_text = user.get_last_seen() %}
@@ -22,7 +22,7 @@
<span title="{{ user.time_registered }}">Registered {{ user.get_registration_delta() }} ago</span><br> <span title="{{ user.time_registered }}">Registered {{ user.get_registration_delta() }} ago</span><br>
{# 0 likes<br>#} {# 0 likes<br>#}
{% with post_count = user.get_post_count() %} {% with post_count = user.get_post_count() %}
{{ post_count }} post{% if post_count > 1 %}s{% endif %}<br> {{ post_count }} post{{ post_count|pluralize() }}<br>
{% endwith %} {% endwith %}
</div> </div>
</div> </div>