I am developing a web application with Flask.I am confused how to add comment feature to posts in a web application. Parts of my database models are a give below
class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
title = db.Column(db.String(140))
body = db.Column(db.String(2000))
timestamp = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
comments = db.relationship('Comment', backref='title', lazy='dynamic')
def get_comments(self):
return Comment.query.filter_by(post_id=post.id).order_by(Comment.timestamp.desc())
def __repr__(self):
return '<Post %r>' % (self.body)
class Comment(db.Model):
id = db.Column(db.Integer, primary_key = True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime)
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
def __repr__(self):
return '<Post %r>' % (self.body)
And post and comment forms as
class PostForm(Form):
post = StringField('post', validators=[DataRequired()])
title = StringField('title', validators=[DataRequired()])
class CommentForm(Form):
comment = StringField('post', validators=[DataRequired()])
The posts are returned by a function blog_posts() in 'User' model
def blog_posts(self):
return Post.query.order_by(Post.timestamp.desc())
Not sure how to return the comments corresponding to each post. After getting posts my code calls render template(index.html). Then how can I obtain comments and print them?. Please help I am a beginner python developer
Since you've defined the relationship between Post and Comment, you can simply do something like the following in your template:
{% if post.comments %}
{% if post.comments.count() > 0 %}
<h2>Comments</h2>
<p>
{% for comment in post.comments %}
<p>{{ comment.body }}</p>
{% endfor %}
</p>
{% endif %}
{% endif %}
Related
I ran into this issue while making this application to collect patient data at a dental clinic. I followed this tutorial. I can get some small things in the code to meet my requirement. But It just displays dots instead of the data. When I add {{ treatment.date }} It displays the date the information is created as expected. This is how it looks. When I add {{ treatment.data | pprint }} It dispalays the dot and prints Undefined. I haven't added the css styling yet.
<ul id="treatment">
{%for treatment in user.info%}
<li>{{ treatment.data }}</li>
{%endfor%}
</ul>
This is how it is written in the html
This is how I enter the data to the database
def home():
if request.method == 'POST':
treatment = request.form.get('treatment')
history = request.form.get('history')
future = request.form.get('future')
payment = request.form.get('payment')
if len(treatment) <1 :
flash('Treatment is too short', category='error')
elif len(history) <1 :
flash('History is too short', category='error')
elif len(future) <1 :
flash('Treatment plan is too short', category='error')
elif len(payment) <1 :
flash('Payment is too short', category='error')
else:
new_record=Info(treatment=treatment,history=history,future=future,payment=payment,user_id=current_user.id)
db.session.add(new_record)
db.session.commit()
flash('Record Added!', category='success')
return render_template("home.html", user=current_user)
This is the code in the models.py
from flask_login import UserMixin
from sqlalchemy.sql import func
class Info(db.Model):
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DateTime(timezone=True), default=func.now())
history = db.Column(db.String(10000))
treatment = db.Column(db.String(10000))
future = db.Column(db.String(10000))
payment = db.Column(db.Integer)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(150))
tel = db.Column(db.Integer, unique=True)
nic = db.Column(db.Integer, unique=True)
info = db.relationship('Info')```
I hope someone can help.
I expect it to display the data regarding treatment,history,future and payment
hello my sqlalchemy just wont commit im pretty sure that my code is correct but i have no idea what why it wont commit
class Movie(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80), unique=True, nullable=False)
year = db.Column(db.String(80), nullable=False)
description = db.Column(db.String(180), nullable=False)
rating = db.Column(db.String(80), nullable=False)
ranking = db.Column(db.String(80), nullable=False)
review = db.Column(db.String(256), nullable=False)
img_url = db.Column(db.String(1000), nullable=False)
def __repr__(self):
return f"id: {self.id} title: {self.title} year: {self.year} description:
{self.description} rating: {self.rating} " \
f"ranking {self.ranking} review: {self.review} img_url: {self.img_url}"
#app.route('/edit', methods=['GET','POST'])
def edit_movie():
movie_id = request.args.get('id')
form = Edit_Form()
print(movie_id)
if request.method == 'POST':
movie_update = Movie.query.filter_by(id=movie_id).first()
movie_update.rating = form.rating.data
movie_update.review = form.review.data
db.session.commit()
return redirect(url_for('home'))
return render_template('edit.html', form=form)
thats my html code
<form action="{{ url_for('edit_movie') }}" method="POST">
{{ form.csrf_token }}
<p>please put in your new rating</p>
{{ form.rating }}
<p>please write your review </p>
{{ form.review }}
{{ form.submit }}
</form>
it seems not to make any changes to the sql data
AttributeError: 'NoneType' object has no attribute 'rating'
movie_update = Movie.query.filter_by(id=movie_id).first()
isn't finding a Movie, and is returning None.
The "movie.update" object that you think you are creating, hasn't been created, whereby not only rating will fail as a method, but I am sur review, too. So, when that fails, nothing will commit
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am trying to relalize full-text search in flask, but nothing happend, there is nothing in traceback and web-application keep working. Please, could you advise me, where I should make some corrections, I try to realize this one first time and dont have such experience before.
event\forms.py
class SearchForm(FlaskForm):
query = StringField('search', validators=[DataRequired()], render_kw={"class": "form-control"})
submit = SubmitField('Submit', render_kw={'class': 'btn btn-secondary border-0'})
event\models.py
class Event(db.Model):
__searchable__ = ['title', 'description']
__table_args__ = {'extend_existing': True}
id = db.Column(db.Integer, unique=True, primary_key=True)
title = db.Column(db.String(50), nullable=False)
genre = db.Column(db.String(100), nullable=True)
url = db.Column(db.String(100), unique=True, nullable=False)
date_start = db.Column(db.Date, nullable=True)
date_finish = db.Column(db.Date, nullable=True)
description = db.Column(db.String(150), nullable=True)
place = db.Column(db.String(50), nullable=True)
address = db.Column(db.String(100), nullable=True)
price = db.Column(db.String, nullable=True)
img_url = db.Column(db.String(100), nullable=True)
text = db.Column(db.Text, nullable=True)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
category = db.relationship('Category', backref='events')
resource_id = db.Column(db.Integer, db.ForeignKey('resource.id'))
resource = db.relationship('Resource', backref='events')
event\views.py
#blueprint.before_request
def before_request():
g.search_form = SearchForm()
#blueprint.route('/search', methods = ['POST'])
def search():
if not g.search_form.validate_on_submit():
return redirect(url_for('event.index'))
return redirect(url_for('event.search_results', query = g.search_form.search.data))
#blueprint.route('/search_results/<query>')
def search_results(query):
search_str = f"%{form.search.data}%"
results = Event.query.filter(Event.name.ilike(search_str), Event.description.ilike(search_str))
return render_template('event/search_results.html',
query = query,
results = results)
event\search_results.html
<!-- extend base layout -->
{% extends "base.html" %}
{% block content %}
{% if results %}
<h3>Here are some results</h3>
{% for result in results %}
{{ result }}
{% endfor %}
{% endif %}
{% endblock %}
Thanks a lot!
I see 2 issues.
On the '/search_results/' route, form.search.data is never defined. Since you included that as a url parameter, you can reference "query" directly in your sqlalchemy query.
The filter clause on your query is currently:
filter(Event.name.ilike(search_str), Event.description.ilike(search_str))
which translates to name and description are both like search_str. I'm assuming that you what you are really looking for is name or description are like search_str.
If that's the case, you can wrap the filter with an "or" clause.
filter(or_(Event.name.ilike(search_str), Event.description.ilike(search_str)))
https://docs.sqlalchemy.org/en/13/core/sqlelement.html#sqlalchemy.sql.expression.or_
i get 'list' object has no attribute 'id' error. I dont know why.
#posts.route("/post/<int:post_id>", methods=['GET','POST'])
#login_required
def course_post(post_id):
post=Post.query.get_or_404(post_id)
chapters=Chapter.query.filter_by(post_id=post_id).all()
chapter_id = chapters.id
videos=Videos.query.filter_by(chapter_id=chapter_id).all()
return render_template('course.html', title=post.course_name, post=post, chapters = chapters)
class Chapter(db.Model):
id = db.Column(db.Integer, primary_key= True)
chapter_no = db.Column(db.Integer)
chapter_name = db.Column(db.String(50))
chapter_desc = db.Column(db.String(50))
chapter_date = db.Column(db.DateTime, default=datetime.utcnow)
vi = db.relationship('Videos', backref='topic', lazy=True)
post_id = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False)
def __repr__(self):
return f"Chapter('{self.chapter_no}', '{self.chapter_name}', '{self.chapter_desc}', '{self.chapter_date}', '{self.post_id}'"
class Videos(db.Model):
id = db.Column(db.Integer, primary_key= True)
video_no = db.Column(db.Integer)
video_name = db.Column(db.String(50), nullable=False, index=True)
video_file = db.Column(db.String(200))
yout_code = db.Column(db.String(200))
video_description = db.Column(db.Text(100))
uploaded_date = db.Column(db.DateTime, default=datetime.utcnow)
rating = db.Column(db.Integer())
chapter_id = db.Column(db.Integer, db.ForeignKey('chapter.id'), nullable=False)
c_v = db.relationship("Chapter", foreign_keys=chapter_id) #
def __repr__(self):
return f"Videos('{self.video_no}','{self.video_name}', '{self.video_file}', '{self.yout_code}', '{self.video_description}', '{self.uploaded_date}', '{self.rating}', '{self.chapter_id}'"
i am trying to get all the videos for each chapter in the Videos table using chapters.id as foreign key
Please what am i doing wrong ?
Try updating your function like this
#posts.route("/post/<int:post_id>", methods=['GET','POST'])
#login_required
def course_post(post_id):
post=Post.query.get_or_404(post_id)
chapters=Chapter.query.filter_by(post_id=post_id).all()
chapter_id = chapters and chapters[0].id
videos=Videos.query.filter_by(chapter_id=chapter_id).all()
return render_template('course.html', title=post.course_name, post=post, chapters = chapters)
Now it uses first chapter ID it founds. I don't know if this is something you want though.
If you want to get list of chapter ids you can do it like this
chapter_id = [c.id for c in chapters]
But I don't know how ORM library you are using handles filtering by lists.
I added this to the parent class (Chapter) of the model.py
medias = db.relationship('Videos', backref='Chapter', lazy='subquery')
The code below pulls the query and sub query of parent and child. This code does that:
chapters = db.session.query(Chapter).filter_by(post_id=post_id).all()
i.e:
#posts.route("/post/<int:post_id>", methods=['GET','POST'])
#login_required
def course_post(post_id):
post=Post.query.get_or_404(post_id)
#chapters=Chapter.query.filter_by(post_id=post_id).all()
chapters = db.session.query(Chapter).filter_by(post_id=post_id).all()
return render_template('course.html', title=post.course_name, post=post, chapters = chapters)
Then in my template, to loop the chapters and videos for each chapter in the template:
{% for v in chapters %}
<h7><span class="plus">+</span>{{ v.chapter_name }}</h7> <br><br>
<div class="descDiv">
{% for media in v.medias %}
<p class="desc">{{ media.video_name }}</p>
{% endfor %}
</div>
{% endfor %}
I am using flask, sqlalchemy, jinja2 and python and I am struggling after getting data from the database and displaying them in my html while they are inside a list and in an anchor to post them with anchor click inside a form to submit them afterwords in another database table.
Here is what I have so far.
My html
<div class="container-fluid">
<div id="training_list">
<h1>List of Exercises</h1>
{% for exercises in exlist %}
<li id="li_ex_list">{{ exercises.name }} | Reputations:
{{ exercises.reps }}</li>
{% endfor %}
</div>
<div id="training_content">
<h1>My Workout Plan</h1>
<form method="POST" action="/my_workouts">
</form>
</br>
<button type="submit" class="btn btn-info">Save my plan</button>
</div>
</div>
My flask-python
class Exercises(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(40), unique=True, nullable=False)
reps = db.Column(db.Integer(), nullable=False)
complete = db.Column(db.Boolean, default=False)
def __init__(self, name, reps, complete):
self.name = name
self.reps = reps
self.complete = complete
def __repr__(self):
return '<Exercises %r>' % self.name
class Traningplan(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
ex_id = db.Column(db.Integer, db.ForeignKey('exercises.id'), nullable=False)
ex_name = db.Column(db.String(40), db.ForeignKey('exercises.name'), nullable=False)
class Usertrainingplan(FlaskForm):
user_id = IntegerField('Userid', render_kw={'readonly': True})
ex_id = IntegerField('Exerciseid', render_kw={'readonly': True})
ex_name = StringField('Exercisename', render_kw={'readonly': True})
#app.route('/my_workouts', methods=['GET', 'POST'])
#login_required
def my_workouts():
exlist = Exercises.query.all()
form = Usertrainingplan()
return render_template('My_Training_Programs.html', exlist=exlist, form=form)
I have tried filtering for complete True/False and passing 2 variables for complete and incomplete(also added them with jinja2 template in my html) but I can't make it work.
---- This part was inside "def_myworkouts():"-----
incomplete = Exercises.query.filter_by(complete=False).all()
complete = Exercises.query.filter_by(complete=True).all()
#app.route('/complete/<id>')
def complete(id):
exercises = Exercises.query.filter_by(id=int(id)).first()
exercises.complete = True
db.session.commit()
return redirect(url_for('my_workouts'))
Additional Information:
Current page looks like this:
current page
So what I want to do is:
Once the user clicks on the links on the left side, I want the text of the links (e.g. Landmine) to be added in the right side of the page where "My workout plan" is, and create a list with all the selected items.
Additionaly I want to be able to place them inside a form and the submit(POST) the form inside a table in my database, with the columns: user_id, ex_id, ex_name as foreign keys. user_id(foreign key) should be the current logged in users id(primary key), ex_id(foreign key) should be the id of the exercise and finally ex_name(foreign key) should be the name of the exercise. The primary keys ofcourse are already commited in the database in the required tables and sames goes with exercises names.
Thanks for your time in advance. Any help highly appriceated.
Stackoverflow you are my only savior