admin管理员组

文章数量:1330576

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 DisplayArtworks: {% 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 DisplayArtworks: {% 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 badges
Add a comment  | 

1 Answer 1

Reset to default 0

I 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.

本文标签: pythonCheck if email in ListField of EmailField inside jinja2 templateStack Overflow