I am working with the omdb api (https://www.omdbapi.com/) and I was able to get the search results to display, but now I am trying to get the movie details when I click on each search result.
Right now I am getting a response of 'Not Found' which I think has something to do with retrieving the movie id, but I haven't been able to figure it out. I appreciate any tips/advice you may have.
app.py:
#app.route('/movies/search_results', methods=['GET'])
def show_search_results():
"""Logic for sending an API request and displaying the JSON response as an HTML. Expects a GET request."""
movies = []
s = request.args.get("s")
results = requests.get(f"{API_BASE_URL}search/movies/",params={"s": s}).json()
results = results['Search']
for movie in results:
movies.append(movie)
return render_template('movies/search_results.html', movies=movies, s=s, id=movie['imdbID'])
#app.route('/movies/<int:id>', methods=['GET'])
def show_movie_details(id):
"""For displaying information about the individual movie. Not a list. GET request only."""
movie = requests.get(f'{API_BASE_URL}movie/{id}')
print(movie)
return render_template('movies/detail.html', movie=movie, id=id)
search_results.html:
{% extends 'base.html' %}
{% block title %} {% endblock %}
{% block nav1 %} active {% endblock %}
{% block content %}
<div class="container-fluid" id="movie-list">
<div class="row row-cols-2 justify-content-center mt-2" style="--bs-gutter-x:0; ">
<p> Search Results for "{{s}}"</p>
<table class="movie-table">
<thead>
<tr>
<th>IMDB ID</th>
<th>Movie Title</th>
<th>Year Released</th>
</tr>
</thead>
<tbody>
{% for movie in movies %}
<tr>
<td>
<a href="/movies/{{id}}" id="id">
{{ id }}
</a>
</td>
<td>
{{ movie['Title'] }}
</td>
<td>
{{ movie['Year'] }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
{% block footer %} {% endblock %}
movies/details.html:
{% extends 'movies/search_results.html' %}
{% block content %}
<div class="card text-center" style="width: 18rem;">
<div class="card-body">
<!-- <div class="d-flex justify-content-between align-items-center mb-3 "> -->
<h5 class="card-title text-center"> Title: {{ movie['Title'] }} </h5>
<form method="POST" action="/movie/add_like/{{ movie['imdbID'] }}" id="messages-form">
<button class="btn btn-sm float-left">
<i class="fa fa-thumbs-up"></i>
</button>
</form>
<p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
</div>
</div>
{% endblock %}
I tried not using int:id in the route and just redirecting to movies/detail.html, but I was still not receiving any results and just viewing the template without any API information on it.
Related
The books are being displayed but when i click on the link it does not lead to the google books.co.in webpage where the book is stored, it displays that the page is not found.
my views.py
def books(request):
if request.method == "POST":
form=DashboardForm(request.POST)
text=request.POST['text']
url="https://www.googleapis.com/books/v1/volumes?q="+text
r = requests.get(url)
answer = r.json()
result_list = []
for i in range(10):
result_dict = {
'title':answer['items'][i]['volumeInfo']['title'],
'subtitle':answer['items'][i]['volumeInfo'].get('subtitle'),
'description':answer['items'][i]['volumeInfo'].get('description'),
'count':answer['items'][i]['volumeInfo'].get('pageCount'),
'categories':answer['items'][i]['volumeInfo'].get('categories'),
'rating':answer['items'][i]['volumeInfo'].get('pageRating'),
'thumbnail':answer['items'][i]['volumeInfo'].get('imageLinks').get('thumbnail'),
'preview':answer['items'][i]['volumeInfo'].get('previewLinks')
}
result_list.append(result_dict)
context={
'form' : form,
'results' :result_list
}
return render(request,'dashboard/books.html',context)
else:
form=DashboardForm()
context={'form' : form}
return render(request,'dashboard/books.html',context)
my books.html template
{% extends 'dashboard/base.html' %}
{% load static %}
{% block content %}
<section class='text-center container'>
<h2><b>SEARCH FOR BOOKS </b></h2>
<p>Enter the search query to obtain your desired book</p><b></b>
<form action="" method="post">
{% csrf_token %}
{{form}}
<input class="btn btn-danger" type="submit" value="Submit">
</form><br>
{% for result in results %}
<a href="{{result.preview}}" target="_blank">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col-md-3">
<img class="img-fluid" src="{{result.thumbnail}}" alt="">
</div>
<div class="col-md-9">
<h3 class="p-0 m-0">{{result.title}}</h3>
<b>
<u>
<h5 class="p-0 m-0">{{result.subtitle}}</h5>
</u>
</b>
{% if result.description %}
<h6 class="p-0 m-1">{{result.description}}</h6>
{% endif %}
<b>
{% if result.categories %}
<h6 class="ml-0 mt-3">Category:
{% for category in result.categories %}
{{category}}
{% endfor %}
</h6>
{% endif %}
{% if result.count %}
<h6 class="ml-0 mt-1">Pages: {{result.count}}</h6>
{% endif %}
{% if result.rating %}
<h6 class="ml-0 mt-1">Rating:{{result.rating}}</h6>
{% endif %}
</b>
</div>
</div>
</div>
</div>
</a>
{% endfor %}
<br>
</section>
{% endblock content %}
I have installed and imported requests and want to redirect to google books page when i click on the book.
enter image description here
The issue seems to be with the value of "preview" in the "result_dict" dictionary. It looks like the "previewLinks" key in the JSON response from the Google Books API does not contain a URL that can be directly accessed.
You can try it like this:
result_dict = {
...
'preview': answer['items'][I]['volumeInfo'].get('previewLinks').get('googlePlay'),
...
}
I have an issue with flask paginate. Upon advice here at Stackoverflow I solved an initial paginate typeerror by changed my code so the paginate takes keywords. This gave me a new issue, since my code now returns an empty list of tickers.
The issue seems to be related to the implementation of paginate with keywords and the filter_by function, since my code returns a list of stocks from all exchanges when i remove the filter for CPH. So below code is working, but gives my tickers for all exchanges and obviously not only the ones with exchange='CPH':
#app.route("/stocks/cphstocks")
#login_required
def cphstocks():
page = request.args.get('page', 1, type=int)
**tickers = Ticker.query.paginate(page=page, per_page=app.config['TICKERS_PER_PAGE'], error_out=False)**
next_url = url_for('cphstocks', page=tickers.next_num) \
if tickers.has_next else None
prev_url = url_for('cphstocks', page=tickers.prev_num) \
if tickers.has_prev else None
return render_template('cphstocks.html', title='Copenhagen Stocks', tickers=tickers.items, next_url=next_url,
prev_url=prev_url)
My code with keywords in paginate and the filtering is shown below. Does anyone know what I'm missing here, since it's not returning the tickers for exchange='CPH'? Advice is much appreciated!
#app.route("/stocks/cphstocks")
#login_required
def cphstocks():
page = request.args.get('page', 1, type=int)
tickers = Ticker.query.filter_by(index="CPH").paginate(
page=page, per_page=app.config['TICKERS_PER_PAGE'], error_out=False)
next_url = url_for('cphstocks', page=tickers.next_num) \
if tickers.has_next else None
prev_url = url_for('cphstocks', page=tickers.prev_num) \
if tickers.has_prev else None
return render_template('cphstocks.html', title='Copenhagen Stocks', tickers=tickers.items, next_url=next_url,
prev_url=prev_url)
And my jinja template:
{% extends "layout.html" %}
{% block content %}
<article class="media content-section">
<div class="media-body">
<h3>Copenhagen listed stocks</h3>
</br>
<p></p>
</div>
</article>
<div class="table-responsive">
<table class="table table-bordered table-hover table-sm w-auto small">
<caption>Stocks listed at Copenhagen stock exchange</caption>
<thead>
<tr>
<th class="text-left"scope="col">Ticker</th>
<th class="text-right"scope="col">Company</th>
</tr>
</thead>
<tbody>
{% for items in tickers %}
<tr>
<td scope="row"> <a href="{{ url_for('stockpage', id=items.id) }}">{{ items.yahoo_ticker }}</td>
<td class="text-right">{{ items.company_name }}</td>
</tr>
{% endfor %}
</tbody>
</table> {% if prev_url %}
Previous page
{% endif %}
{% if next_url %}
Next page
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="content-section">
<h3>New menu </h3>
<p class='text-muted'>You can put any information here you'd like.
<ul class="list-group">
<li class="list-group-item list-group-item-light">Visit Yahoo Finance</li>
<li class="list-group-item list-group-item-light">Update1</li>
<li class="list-group-item list-group-item-light">Calendars</a></li>
<li class="list-group-item list-group-item-light">etc</a></li>
</ul>
</div>
</div>
{% endblock content %}
Solved it by using filter instead of filter_by, so code that works is as below:
tickers = Ticker.query.filter(Ticker.exchange.contains('CPH')).paginate(page=page, per_page=app.config['TICKERS_PER_PAGE'], error_out=False)
Problem:
I am developing an application in django that uses paginator for the list page of a model, it is set to display 25 instances of the model per page, when i view the first page everything works fine but when i move to the second page it shows some values from the first again. i have checked the database and there is no data duplication either.
Cause/attempted solutions:
while not 100% i believe the problem originates from the order_by in the queryset but even after changing and removing the problem persists
Details:
snips of list for the first and second page
First: https://imgur.com/tyY5xu0
Second: https://imgur.com/UcGWEFN (note CO01, 4 and 5 appear again)
Views.py:
def view_jobs(request):
query_results = Job.objects.select_related('contract').order_by('-active', '-order_date')
paginate = Paginator(query_results, 25)
page_no = request.GET.get('page')
page_obj = paginate.get_page(page_no)
context = {"query_results": page_obj}
return render(request, 'view_jobs.html', context)
view_jobs.html:
<table id="PageTable" class="table table-striped">
<thead>
<tr>
<th class="dropdown">
<a class="dropdown-toggle" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
<h6>Number</h6>
</a>
</th>
</tr>
</thead>
<tbody>
{% for item in query_results %}
<td>
<small>{{ item|filter_prep:"order" }}</small>
{% if item.help_text %}
<small style="color: grey">{{ item.help_text }}</small>
{% endif %}
{% for error in item.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<span class="step-links">
{% if query_results.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ query_results.number }} of {{ query_results.paginator.num_pages }}.
</span>
{% if query_results.has_next %}
next
last »
{% endif %}
</span>
</div>
feel free to ask for any extra details.
I'm new to django so i could be asking a dumb question, but how am i supposed to forward URL A's named parameter to URL B?
For example:
URL A = https://stackoverflow.com/questions?parameter=1
URL B = https://stackoverflow.com/ask
What i actually want is:
URL B = https://stackoverflow.com/ask?parameter=1
I need to do this because i need to pass those parameters to the view that is being called at the second url, could someone help me?
EDIT1
The views that are at play are this two:
class HostServiceListView(BaseFilterView, ListView):
template_name = 'services/service_list.html'
model = HostService
paginate_by = 15
context_object_name = 'services'
filterset_class = HostServiceFilterSet
def exportHostServices(request):
hsqs = HostService.objects.filter(hostname__icontains=request.GET.get("hostname_input", ''),\
ip__icontains=request.GET.get("ip_input", ''),\
port__icontains=request.GET.get("port_input", ''),\
servicename__icontains=request.GET.get("servicename_input", ''))
df = read_frame(hsqs)
# my "Excel" file, which is an in-memory output file (buffer)
# for the new workbook
excel_file = IO()
# pylint shows a false positive error here,
# so the alert is suppressed with the comment after the code
xlwriter = pd.ExcelWriter(excel_file, engine='xlsxwriter') # pylint: disable=abstract-class-instantiated
df.to_excel(xlwriter, 'Host Services')
xlwriter.save()
xlwriter.close()
# rewind the buffer
excel_file.seek(0)
# set the mime type so that the browser knows what to do with the file
response = HttpResponse(excel_file.read(),\
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
# set the file name in the Content-Disposition header
response['Content-Disposition'] = 'attachment; filename=Anagrafica-Servizi.xlsx'
return response
The urls.py is configured this way:
urlpatterns = [
path('services/', HostServiceListView.as_view(), name='services'),
path('services/exportHostServices/', exportHostServices, name='exportHostServices'),
path('', IndexFilterView, name="index")
]
Finally, the button i've got in html that needs to call exportHostServices with the query-string so i can get the parameters:
services/service_list.html
{% extends 'services/base.html' %}
{% load paginatedfilter %}
{% block title %}Host Services{% endblock title %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Service Registry</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group mr-2">
<form action="{% url 'exportHostServices' %}?{{ request.GET.urlencode }}">
<input type="submit" class="btn btn-sm btn-outline-secondary" value="Export">
</form>
</div>
</div>
</div>
<div class="table-responsive table-sm">
<form method="GET">
<input type="submit" class="btn-hidden"/>
<table class="table table-hover table-light table-striped">
<thead class="thead-light">
<tr>
<th>{{ filter.form.hostname_input }}</th>
<th>{{ filter.form.ip_input }}</th>
<th>{{ filter.form.port_input }}</th>
<th>{{ filter.form.servicename_input }}</th>
</tr>
</thead>
<tbody>
{% for service in services %}
<tr>
<td>{{ service.hostname }}</td>
<td>{{ service.ip }}</td>
<td>{{ service.port }}</td>
<td>{{ service.servicename }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?{% param_replace page=page_obj.previous_page_number %}" aria-label="previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %}
{% for i in paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item active" aria-current="page">
<span class="page-link">
{{ i }}
<span class="sr-only">(current)</span>
</span>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?{% param_replace page=i %}">{{ i }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?{% param_replace page=page_obj.next_page_number %}" aria-label="next">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %}
</ul>
{% endif %}
</form>
</div>
{% endblock content %}
Figured out atlast what was wrong with the code. The problem was that the form where i passed the querystring was defaulted at GET:
<form action="{% url 'exportHostServices' %}?{{ request.GET.urlencode }}">
The fix was to simply convert it to a POST form so the querystring could be passed to the view:
<form action="{% url 'exportHostServices' %}?{{ request.GET.urlencode }}" method="post">
I am working on library website in which I want to display data from database which is Book name and description. But I'm not able to do that. Here is my code
views.py
from django.shortcuts import render
from .models import *
def index(request):
book_list = Book.objects.all()
return render(request,template_name='index.html', context={'book_list':book_list})
index.html
{% extends "base_generic.html" %}
{% block new_books %}
{% for b in book_list %}
<div class="card">
<img class="card-img-top" src=".." alt="Image">
<div class="card-body">
<h5 class="card-title">{{ book_list }} </h5>
<p class="card-text">Hello this is card text</p>
<a class="btn btn-primary">View this book</a>
</div>
</div>
{% endfor %}
{% endblock %}
You should work with b variable instead of book_list inside of for loop.
If your Book model contains title field, your code might look like this:
{% extends "base_generic.html" %}
{% block new_books %}
{% for b in book_list %}
<div class="card">
<img class="card-img-top" src=".." alt="Image">
<div class="card-body">
<h5 class="card-title">{{ b.title }} </h5>
<p class="card-text">Hello this is card text</p>
<a class="btn btn-primary">View this book</a>
</div>
</div>
{% endfor %}
{% endblock %}