0

I'm trying to complete an assignment that links up Python, Flask, and SQL. I have a database of books with title, author, year, and isbn information. When a search request is carried out a list of applicable results is generated with hyperlinks on each of the titles. I want to create a dynamic url that is dependent on the title that is clicked. The isbn of the clicked book title should be part of the url. However, I don't really know how to achieve this. I've tried the following, but I'm stuck and would appreciate some help.

Here is the application.py

import os

from flask import Flask, redirect, render_template, request, session, url_for
from flask_session import Session
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from helpers import login_required
import requests

app = Flask(__name__)
# Check for environment variable
if not os.getenv("DATABASE_URL"):
    raise RuntimeError("DATABASE_URL is not set")

# Configure session to use filesystem
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)

# Set up database
engine = create_engine(os.getenv("DATABASE_URL"))
db = scoped_session(sessionmaker(bind=engine))


@app.route("/", methods=["GET", "POST"])
@login_required
def index():
    """Search for books"""

    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        # Ensure username was submitted
        if not request.form.get("search_term"):
            return render_template("error.html", message="Enter a book title, author, or ISBN.")

        # Search by ISBN, book title or book author
        search_term=request.form.get("search_term")
        rows = db.execute("SELECT author, title, isbn, year FROM books WHERE (author iLIKE '%"+search_term+"%' OR title iLIKE '%"+search_term+"%' OR isbn iLIKE '%"+search_term+"%')").fetchall()

        if not len(rows) >= 1:
            return render_template("error.html", message="Sorry, no results match your entry.")

        # populate results one dictionary at a time
        dict, results = {}, []
        for row in rows:
            # row.items() returns an array like [(key0, value0), (key1, value1)]
            for column, value in row.items():
                # join up the dict from the previous iteration (**dict) with the new key-value pair **{column: value}
                dict = {**dict, **{column: value}}
            results.append(dict)

        # Redirect user to results page
        return render_template("results.html", results=results)

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("index.html")

@app.route("/api/<string:isbn>", methods=["GET"])
@login_required
def books(isbn):
    """Show book details"""

    # Make sure book exists
    return render_template("book.html")
    #TODO


@app.route("/results", methods=["POST"])
def results():
    """Print results to screen"""

    return render_template("results.html")

And here is the results.html

{% extends "layout.html" %}

{% block title %}
    Results
{% endblock %}

{% block main %}

<script>
  book=document.getElementsByClassName(book)
</script>

    <table style="margin-left: 5%" class="table table-responsive-sm table-sm table-borderless">

        <thead>
            <tr align="left">
                <th>Author</th>
                <th>Title</th>
                <th>Year</th>
                <th>ISBN</th>
            </tr>
        </thead>
        <tbody>
            {% for result in results %}
                {% if results != None %}
                    <tr align="left">
                        <td>{{ result['author'] }}</td>
                        <td class="book"><a href="{{url_for('books', result['isbn'])}}" style="color: black;">{{ result['title'] }}</a></td>
                        <td>{{ result['year'] }}</td>
                        <td>{{ result['isbn'] }}</td>
                    </tr>
                {% endif %}
            {% endfor %}
        </tbody>
    </table>

{% endblock %}

I know the syntax for including the isbn number is incorrect ({{url_for('books', result['isbn']}}) but I thought someone might see more clearly what I'm trying to do if I show everything.

davidism
  • 121,510
  • 29
  • 395
  • 339
mich-ish
  • 48
  • 9

1 Answers1

1

You definitely on the right track from what I can see. all that is left is for you to query the database using the isbn as the search parameter in your book route. you can then handle your search results and display it appropriately in the book.html template.

haibeey
  • 41
  • 1
  • 1