Context:
I have a class as follows:
class DisplayArtwork(Document):
name = StringField(required=True)
email = EmailField(required=True)
country = StringField(required=True)
phone = StringField()
artname = StringField(required=True)
medium = StringField(required=True)
caption = StringField(required=True)
filename = StringField(required=True)
votes = ListField(EmailField())
published = DateTimeField(required=True)
I then send DisplayArtwork.objects
into a flask/jinja2 template as follows:
@app.route("/gallery")
def gallery():
return render_template("gallery.html", artworks=DisplayArtwork.objects)
Inside the template is a for loop that iterates through all of the DisplayArtwork
s: {% for artwork in artworks %}
My question is: can I check whether the current user's email (current_user.get_id()
) is inside of the ListField(EmailField())
?
What I have tried:
First, I check whether the current user is authenticated, then I check if artwork['votes'][current_user.get_id()]
is defined.
{% if current_user.is_authenticated %}
{% if artwork['votes'][current_user.get_id()] is defined%}
<button id="{{ artwork['filename']}}" type="button" class="btn btn-success" onclick='upvote(`{{artwork["filename"]}}`)'>Upvotes: {{artwork['votes']|length}}</button>
{% else %}
<button id="{{ artwork['filename']}}" type="button" class="btn btn-outline-success" onclick='upvote(`{{artwork["filename"]}}`)'>Upvotes: {{artwork['votes']|length}}</button>
{% endif %}
{% else %}
<a href="/login" class="btn btn-success">Login to Upvote</a>
{% endif %}
The upvote()
function works like this:
function upvote(filename) {
const formData = new FormData();
formData.append('filename', filename);
fetch('/upvote', {
method: 'post',
body: formData
});
upvotebutton = document.getElementById(filename);
if (!upvotebutton) {alert('Error: ${filename} button not found');}
if (upvotebutton.classList.contains('btn-outline-success')) {
upvotebutton.classList.remove('btn-outline-success');
upvotebutton.classList.add('btn-success');
upvotebutton.innerHTML = 'Upvotes: ' + (parseInt(upvotebutton.innerHTML.split(' ')[1]) + 1);
}
else if (upvotebutton.classList.contains('btn-success')) {
upvotebutton.classList.remove('btn-success');
upvotebutton.classList.add('btn-outline-success');
upvotebutton.innerHTML = 'Upvotes: ' + (parseInt(upvotebutton.innerHTML.split(' ')[1]) - 1);
}
}
This is then handled by this function on the backend:
@app.route("/upvote", methods=["POST"])
def upvote():
if current_user.is_authenticated:
artwork = DisplayArtwork.objects(filename=request.form["filename"])
if artwork:
response = None
try:
artwork.update(pull__votes=current_user.get_id())
response = "downvoted"
except KeyError:
artwork.update(add_to_set__votes=[current_user.get_id()])
response = "upvoted"
return response, 200
return "Failed to upvote", 500
return "Login to upvote", 401
Unfortunately, this always shows that the user has not upvoted.
How can I make the vote functionality work?
Context:
I have a class as follows:
class DisplayArtwork(Document):
name = StringField(required=True)
email = EmailField(required=True)
country = StringField(required=True)
phone = StringField()
artname = StringField(required=True)
medium = StringField(required=True)
caption = StringField(required=True)
filename = StringField(required=True)
votes = ListField(EmailField())
published = DateTimeField(required=True)
I then send DisplayArtwork.objects
into a flask/jinja2 template as follows:
@app.route("/gallery")
def gallery():
return render_template("gallery.html", artworks=DisplayArtwork.objects)
Inside the template is a for loop that iterates through all of the DisplayArtwork
s: {% for artwork in artworks %}
My question is: can I check whether the current user's email (current_user.get_id()
) is inside of the ListField(EmailField())
?
What I have tried:
First, I check whether the current user is authenticated, then I check if artwork['votes'][current_user.get_id()]
is defined.
{% if current_user.is_authenticated %}
{% if artwork['votes'][current_user.get_id()] is defined%}
<button id="{{ artwork['filename']}}" type="button" class="btn btn-success" onclick='upvote(`{{artwork["filename"]}}`)'>Upvotes: {{artwork['votes']|length}}</button>
{% else %}
<button id="{{ artwork['filename']}}" type="button" class="btn btn-outline-success" onclick='upvote(`{{artwork["filename"]}}`)'>Upvotes: {{artwork['votes']|length}}</button>
{% endif %}
{% else %}
<a href="/login" class="btn btn-success">Login to Upvote</a>
{% endif %}
The upvote()
function works like this:
function upvote(filename) {
const formData = new FormData();
formData.append('filename', filename);
fetch('/upvote', {
method: 'post',
body: formData
});
upvotebutton = document.getElementById(filename);
if (!upvotebutton) {alert('Error: ${filename} button not found');}
if (upvotebutton.classList.contains('btn-outline-success')) {
upvotebutton.classList.remove('btn-outline-success');
upvotebutton.classList.add('btn-success');
upvotebutton.innerHTML = 'Upvotes: ' + (parseInt(upvotebutton.innerHTML.split(' ')[1]) + 1);
}
else if (upvotebutton.classList.contains('btn-success')) {
upvotebutton.classList.remove('btn-success');
upvotebutton.classList.add('btn-outline-success');
upvotebutton.innerHTML = 'Upvotes: ' + (parseInt(upvotebutton.innerHTML.split(' ')[1]) - 1);
}
}
This is then handled by this function on the backend:
@app.route("/upvote", methods=["POST"])
def upvote():
if current_user.is_authenticated:
artwork = DisplayArtwork.objects(filename=request.form["filename"])
if artwork:
response = None
try:
artwork.update(pull__votes=current_user.get_id())
response = "downvoted"
except KeyError:
artwork.update(add_to_set__votes=[current_user.get_id()])
response = "upvoted"
return response, 200
return "Failed to upvote", 500
return "Login to upvote", 401
Unfortunately, this always shows that the user has not upvoted.
How can I make the vote functionality work?
Share Improve this question asked Nov 27, 2024 at 0:50 wenbangwenbang 115 bronze badges1 Answer
Reset to default 0I figured it out!
Here's what I changed.
First of all, in the jinja2 template, I checked the email like this: {% if current_user.get_id() in artwork.votes %}
instead of {% if artwork['votes'][current_user.get_id()] is defined%}
.
Next, I changed the upvote function to be like this:
@app.route("/upvote", methods=["POST"])
def upvote():
if current_user.is_authenticated:
artwork = DisplayArtwork.objects(filename=request.form["filename"]).first()
if artwork:
user_email = current_user.get_id()
if user_email in artwork.votes:
artwork.update(pull__votes=user_email)
return "downvoted", 200
else:
artwork.update(add_to_set__votes=user_email)
return "upvoted", 200
return "Failed to upvote", 500
return "Login to upvote", 401
artwork.update(pull__votes=user_email)
won't throw KeyError so I changed it to manually check whether the email was in the list and then decide what to do.
I also fot to add .first()
to get one artwork instead of a list.