0

I am trying to load an image, based on what the user selects in a select box.

html:

<div class='image-container' id='image'>
        <h3>Index: {{ photo_index }}</h3>
        <h3>Filename: {{ image }}</h3>
        <img src="{{ url_for('images.static', filename=image) }} " id="the-photo">
</div>
<div class='button-container' id='buttons'>
   <form action="" method="post">
       <input type="hidden" name="prev-next-buttons">
       <input type="submit" value="Show prev photo" name='prev_photo'>
       <input type="submit" value="Show next photo" name='next_photo'>
       <br/>
       <input type="submit" value="Show random photo" name='random_photo'>
       <button type='button' id='rotate-button' onclick="rotateMe('#the-photo')">Rotate Photo</button>
   </form>
   <h3>Choose image from list:</h3>
   <form method="post">
       <input type="hidden" name="photo-select">
       <select id="select-image" onfocus='this.size=5;' onblur='this.size=1' onchange="this.size=1;  this.blur(); this.form.submit()">
           {% for eimage in image_list %}
               <option {% if eimage == image %} selected {% endif %}
                href = "{{ url_for('main', chosen_image=eimage) }}"
                >
                   {{eimage}}
               </option>
           {% endfor %}
       </select>
   </form>
</div>

routes.py

CUR_PHOTO_INDEX = 0
images = os.listdir(IMAGE_FOLDER)
image_urls = create_urls(images)
image_urls.append('favicon.ico')
num_images = len(image_urls) - 1

@app.route("/", methods=["GET", "POST"])
def main(chosen_image="Penguins.jpg"):
    # if request.method == "POST":
    global CUR_PHOTO_INDEX
    if request.method == "POST":
        if 'prev-next-buttons' in request.form:
            CUR_PHOTO_INDEX = return_index(request.form, CUR_PHOTO_INDEX)
            # print("Showing index", CUR_PHOTO_INDEX)
        elif 'photo-select' in request.form:
            CUR_PHOTO_INDEX = image_urls.index(chosen_image)
            # print("\n", indx, "\n")
            print("\n", chosen_image, CUR_PHOTO_INDEX, "\n")
    return render_template('index.html',
                           title="Local Image Viewer",
                           photo_index=CUR_PHOTO_INDEX,
                           image=image_urls[CUR_PHOTO_INDEX],
                           image_list=image_urls)

What I'm expecting to happen, is when the user selects an option from the list, it sends that image name (a string, eimage) to main(), and then looks for that index in image_urls.index(chosen_image). But, whenever I do select an option, it just rpints the "Penguins.jpg" and its index over and over.

What am I overlooking to send the selected image name to the main() function?

BruceWayne
  • 22,923
  • 15
  • 65
  • 110
  • 1
    When would your second if ever be true? There's no 'prev-next-buttons' in your form as far as I can see. And what is supposed to be populating the 'photo-select' hidden input? (And, you absolutely definitely should not be using a global for CUR_PHOTO_INDEX.) – Daniel Roseman Apr 08 '19 at 21:10
  • 1
    Why do you have `global CUR_PHOTO_INDEX` btw? – roganjosh Apr 08 '19 at 21:10
  • @DanielRoseman - Sorry, I tried to post as little code as I could to keep it succinct, but have updated it. I have a global `CUR_PHOTO_INDEX` because, despite declaring it above, I get `local variable 'CUR_PHOTO_INDEX` referenced before assignment when I don't include that. (Edit: the `global` declaration was a kludge from earlier. I've since removed it, and simply declared it in the `main()` function. ...but now the prev/next buttons don't do anything.) – BruceWayne Apr 08 '19 at 21:15
  • @roganjosh - so I can use that variable in the function. I declared it above the function but have to declare it in the function since I assign something to it. I am currently trying to work around that. – BruceWayne Apr 09 '19 at 00:47
  • I have even tried doing `global CUR_PHOTO_INDEX // CUR_PHOTO_INDEX = 0` above `@app.route()`, and changed to `def main(CUR_PHOTO_INDEX, chosen_image=image_urls[0]):` but get an error `main() missing 1 required positional argument: 'CUR_PHOTO_INDEX'` – BruceWayne Apr 09 '19 at 04:12

2 Answers2

2

That's because you have not defined a query parameter in your route. url_for will return an URL to your endpoint, and since it has no way of communicating the value for chosen_image via this URL, your method will always use the default value.

Try something like

@app.route("/", methods=["GET", "POST"])
@app.route("/<chosen_image>", methods=["GET", "POST"])
def main(chosen_image="Penguins.jpg"):
    # the rest of your method

F. Pareto
  • 304
  • 2
  • 10
  • So I updated the function to be `def main(chosen_image=image_urls[0]):` and added the line as you suggested, but am still not getting the chosen image as the image showing...I suspect the reason is my `gloabl CUR_PHOTO_INDEX` in there, that I need to fix/work around... – BruceWayne Apr 09 '19 at 04:01
  • Could you update your question to reflect the current state of your code? – F. Pareto Apr 09 '19 at 17:23
  • I think I found my solution, I need to use a class to advance the photo index, avoiding the global variable. This is part of that solution though, so thanks very much! (I'm fine-tuning it and making sure it works, but will post as an Answer later). – BruceWayne Apr 09 '19 at 17:44
0

As @F. Pareto, part of the issue was I wasn't passing the parameter to the app.route("/").

The second issue was my use of a global variable to try and keep track of the current index. Thanks greatly to this Question/Answer, I have created a class to keep track of the index and can iterate through that.

html:

<div class='image-container' id='image'>
   <h3>Index: {{ photo_index }}</h3>
   <h3>Filename: {{ image }}</h3>
   <img src="{{ url_for('images.static', filename=image) }} " id="the-photo">
 </div>
 <div class='button-container' id='buttons'>
    <form action="" method="post">
        <input type="hidden" name="prev-next-buttons">
        <input type="submit" value="Show prev photo" name='prev-photo'>
        <input type="submit" value="Show next photo" name='next-photo'>
        <br/>
        <input type="submit" value="Show random photo" name='random-photo'>
        <button type='button' id='rotate-button' onclick="rotateMe('#the-photo')">Rotate Photo</button>
    </form>
    <h3>Choose image from list:</h3>
    <form method="post">
        <input type="hidden" name="photo-select">
        <select name="select-image" onfocus='this.size=5;' onblur='this.size=1' onchange="this.size=1;  this.blur(); this.form.submit()">
            {% for eimage in image_list %}
                <option 
                {% if eimage == image %} selected {% endif %}
                value = {{ eimage }}
                >
                    {{eimage}}
                </option>
            {% endfor %}
        </select>
    </form>
</div>

routes.py

images = os.listdir(IMAGE_FOLDER)
def create_urls(files):
    image_urls = []
    for file in files:
        if file.endswith(".jpg"):
            image_urls.append(file)
    return image_urls


image_urls = create_urls(images)
image_urls.append('favicon.ico')
# Subtract 2 below, so you don't include the
# favicon.ico
num_images = len(image_urls) - 2


class Photo_Index():
    def __init__(self, index=0):
        self.index = index

    def increase_number(self):
        if self.index == num_images:
            self.index = 0
        else:
            self.index = self.index + 1
        return self.index

    def decrease_number(self):
        if self.index == 0:
            self.index = num_images
        else:
            self.index = self.index - 1
        return self.index

    def random_number(self):
        self.index = random.randint(0, num_images)
        return self.index

    def set_number(self, number):
        self.index = number
        return self.index

photo_index_obj = Photo_Index()


def update_index(rqst):
    if 'prev-photo' in rqst.form:
        photo_index_obj.decrease_number()
    elif 'next-photo' in rqst.form:
        photo_index_obj.increase_number()
    elif 'random-photo' in rqst.form:
        photo_index_obj.random_number()


@app.route("/", methods=["GET", "POST"])
@app.route("/<chosen_image>", methods=["GET", "POST"])
def main(chosen_image=None):
    if request.method == "POST":
        if 'prev-next-buttons' in request.form:
            update_index(request)
        elif 'photo-select' in request.form:
            img = request.form.get("select-image")
            photo_index_obj.set_number(image_urls.index(str(img)))
        else:
            print("not a real POST")
    if request.method == "GET":
        if chosen_image is not None:
            photo_index_obj.set_number(image_urls.index(chosen_image))
    return render_template('index.html',
                           title="Local Image Viewer",
                           photo_index=photo_index_obj.index,
                           image=image_urls[photo_index_obj.index],
                           image_list=image_urls)
BruceWayne
  • 22,923
  • 15
  • 65
  • 110