I’m working with the Google Books API and I’m not so sure about the way I’m going to get the search data and return it to the user. I will describe the path here and I would like to know if you would do something different.
First, I receive a search request from the user via a form inside index.html
:
<form action='/lookup' method="post">
<input type="text" name="search" placeholder="Search by title, author, publisher, release, ISBN ...">
<button type="submit">Buscar</button>
{% block search %}{% endblock %}
</form>
So in an app.py
I get this request like this:
@app.route("/lookup", methods=["GET", "POST"])
@login_required
def search():
"""Get book search."""
if request.method == "POST":
result_check = is_provided("search")
if result_check is not None:
return result_check
search = request.form.get("search").upper()
search = lookup(search)
if search is None:
return "Invalid Search"
return render_template("search.html", search={
'totalItems': search['totalItems'],
'title': search['title'],
'authors': search['authors']
})
else:
return render_template("/")
Next, I access a lookup function in helpers.py
:
def lookup(search):
"""Look up search for books."""
# Contact API
try:
url = f'https://www.googleapis.com/books/v1/volumes?q={search}&key=MYAPIKEY'
response = requests.get(url)
response.raise_for_status()
except requests.RequestException:
return None
# Parse response
try:
search = response.json()
return {
"totalItems": int(search["totalItems"]),
"items": search["items"]
}
except (KeyError, TypeError, ValueError):
return None
To return the results to the user I have a search.html
that is still under construction:
{% extends "index.html" %}
{% block search %}
<p>Total Items: {{search['totalItems']}}</p>
<table>
<tr>
<td>
<img src="{{search['items'][0]['volumeInfo']['imageLinks']['thumbnail']}}">
<p>Título: {{search['items'][0]['volumeInfo']['title']}}</p>
<p>Autor(a): {{search['items'][0]['volumeInfo']['authors']}}</p>
</td>
<td>
<img src="{{search['items'][2]['volumeInfo']['imageLinks']['thumbnail']}}">
<p>Título: {{search['items'][2]['volumeInfo']['title']}}</p>
<p>Autor(a): {{search['items'][2]['volumeInfo']['authors']}}</p>
</td>
</tr>
</table>
{% endblock %}
Finally, my question: is this path I am following to access the API and return the data to the user the most recommended? Would you do anything other than that?
-
1\$\begingroup\$ Could you clarify what Python framework you are using? \$\endgroup\$200_success– 200_success2021年05月27日 05:49:26 +00:00Commented May 27, 2021 at 5:49
-
1\$\begingroup\$ Hi, It is pure Python. I am only using the package Flask. \$\endgroup\$ARNON– ARNON2021年05月27日 12:02:27 +00:00Commented May 27, 2021 at 12:02
1 Answer 1
Split search()
up into two functions, each accepting only one method, and dispose of your if
.
There's a little bit of religion around this, but HTML5 accepts both "naive HTML" and XHTML-compatible tag closure, so this:
<input type="text" name="search">
is also accepted as
<input type="text" name="search" />
and the latter is (1) more explicit on where the tag ends and (2) is more broadly compatible.
This:
request.form.get("search").upper()
does not benefit from get
, because you don't provide a default. Either allow the crash on a missing parameter, i.e. request.form['search']
, or provide a default to get
, likely the empty string.
This:
search = lookup(search)
is ill-advised, because it swaps types on the same symbol. The input is a string and the output is a dictionary.
This:
url = f'https://www.googleapis.com/books/v1/volumes?q={search}&key=MYAPIKEY'
first should not hard-code your API key directly into the string, and second should not format any query parameters into the string. Instead, pass params={...}
into get()
.
This:
except requests.RequestException:
return None
is fairly catastrophic for the application's ability to tell maintainers and users what went wrong. You're going to want to log the exception, and translate it into an appropriate failure message returned to your own caller.
This:
requests.get(url)
should use the response in a with
.
Your search.html
template is deeply bizarre. Where I would expect to see a for
, you've only shown the first and third items?
Ensure that you're telling the browser that your content is in Spanish.
This:
action='/lookup'
needs to use double quotes.
-
1\$\begingroup\$ Thanks @Reinderien! You helped me a lot!! As I told, the
search.html
is under construction. I really appreciate your help! \$\endgroup\$ARNON– ARNON2021年05月26日 23:23:45 +00:00Commented May 26, 2021 at 23:23