I have an html page that displays documents and their preview sorted by their pagerank value. I want to make it so that when the user clicks a document, it takes them to the corresponding document
html:
<div class="col-sm-6 text-white">
<h1 class="display-1">Boolean Model</h1>
{% for doc, pr in q_res_bool.items() %} // e.g. "doc1.txt: 0.6459865341"
<a href="/document">
<div class="m-3">
<h2 class="mt-5">{{ doc }} <span class="h6 text-dark-emphasis">({{ pr[:5] }})</span></h2>
<p class="col-7">{{ boolPreview[doc] }}</p>
</div>
</a>
{% endfor %}
</div>
This is the general idea that i want (document route in app.py):
# Document page
#app.route('/document')
def view_document(doc):
with open(f"docs/{doc}") as f:
document = f.read()
return render_template("result.html", document=document)
How do i pass the variable in the loop to this function as parameter?
I thought of putting something along the lines of
<input type="hidden" id="{{ doc }}" name="{{ doc }}" value="{{ doc }}">
in my html, going by this article and getting the value with request.args.get() but i end up with the same problem of not knowing what to pass as parameter
example screenshot of html:
I solved it by changing my link tag to <a href="/docs/{{ doc }}">
and then accessing it via a variable rule in my app.py:
#app.route('/docs/<doc>', methods=['GET', 'POST'])
def view_document(doc):
print("route received")
with open(f"docs/{doc}") as f:
document = f.read()
return render_template("result.html", document = document, title = doc)
Related
I have aproblem when i try to render the JSON data in the HTML template.
I dont know if the problem is in the Python code or in the HTML code.
I've tested the python code of the search funtion (returns a JSON with a list o products) and returns a valid JSON (the JSON than i expected).
But i still havig issues with the HTML.
I've searched a lot, but nothing helped me.
The function of the HTML template is to display the products of my ecommerce. In this template i'll show the results of a previous search.
Here is the code of the python app:
search = request.form['search']
if search != "":
for product in mycol.find({"name": {"$regex": f".*{search}.*", "$options": "i"}}):
datainfo = json.loads(json_util.dumps(product))
return render_template("search.html", product=datainfo)
else:
return render_template("index.html")
The HTML card code:
<div>
<div class="results_container">
<div class="row">
<div class="card">
<ul>
{% for product in product %}
<li class="table-row">
<div id="Product">{{product['name']}}</div>
<div id="Price">{{product['price']}}</div>
<div id="Description">{{product['description']}}</div>
<div id="Category">{{product['category']}}</div>
<div id="Seller">{{product['user_name']}}</div>
<div>
Buy
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
`
so far this is what I came up with
#html ask user to input information including an image
<div class="form-group">
<input autocomplete="off" autofocus class="form-control" name="name" placeholder="name" type="text">
</div>
<div class="form-group">
<input class="form-control" name="subject" placeholder="subject" type="text">
</div>
<div class="form-group">
<input class="form-control" name="experience" placeholder="experience" type="text">
</div>
<div class="form-group">
<input class="form-control" name="phone" placeholder="puone-number" type="number">
</div>
<div class="form-group">
<input type="file" name="pic" id="pic">
</div>
<button class="btn btn-primary" type="submit">Register</button>
</form>
flask
#app.route("/register", methods=["GET", "POST"])
def register():
"""Show teacher registering menu"""
if request.method == "GET":
return render_template("register.html")
else:
# get the user input
name = request.form.get("name")
sub = request.form.get("subject")
exp = request.form.get("experience")
phone = request.form.get("phone")
f = request.files['pic']
pic = f.save(secure_filename(f.filename))
if not name or not sub or not exp or not phone:
return "404"
# insert in the database
sql = "INSERT INTO teachers (name, sub, exp, phone, pic) VALUES (?, ?, ?, ?, ?)"
db.execute(sql, name, sub, exp, phone, pic)
# inform the user for the success of the process
return render_template("success.html")
showing the results on html
<div>
{% for i in query %}
<div class="media bg-primary text-white">
<img class="align-self-end mr-3" src={{ i['pic'] }} alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0">Mr. {{ i['name'] }}</h5>
<ul class="list-group list-group-flush text-dark">
<li class="list-group-item">subject: {{ i['sub'] }},</li>
<li class="list-group-item">experience: {{ i['exp'] }},</li>
<li class="list-group-item">Contact number: {{ i['phone'] }}</li>
</ul>
</div>
</div>
<br>
{% endfor %}
</div>
but right now every time I try it I find the value of the image column in my sql table to be NULL.
How can I fix that
pic = f.save(secure_filename(f.filename))
The save method returns None, so here pic will be None.
I think you intended to write its filename to the database, so perhaps change this to:
pic = secure_filename(f.filename)
f.save(pic)
Now pic is the filename on your server, so you just need to reconstruct this wherever the file is viewed.
Of course be aware that this uses the filename of the file which was uploaded by the user. You may wish to avoid this, incase of duplicates or just for cleanliness. See this other answer I wrote regarding that.
EDIT: Regarding your template.
When it comes to loading the picture in the template, let's assume the filename came through as image.jpg, and you use your exisiting code:
<img src={{ i['pic'] }}>
You could view the source of the rendered page, and see:
<img src=image.jpg>
Two problems with this:
that attribute should have quotes (<img src="image.jpg">)
that's trying to load the file from whichever path is rendered in the browser, so if the URL was http://example.com/subdir/ it's looking for the image at http://example.com/subdir/image.jpg. This can also be verified in the Network tab of your browsers dev tools.
The solution, build the URL with flask's url_for function:
<img src="{{ url_for('static', filename=i['pic']) }}">
This, of course, assumes that you've saved the file to the static directory on your server. You may wish to ensure this in the python code:
import os
# ...
pic = secure_filename(f.filename)
f.save(os.path.join('static', pic))
Currently I am trying to create a dynamic filter for listing model objects in a template. Here is the django view:
def view_data(request):
text = request.GET.get('text')
persons = None
if text:
try:
persons = models.Person.objects.get(code__regex=text)
except models.Person.DoesNotExist:
pass
return render(request, 'view_data.html',
{'persons': persons if not isinstance(persons, models.Person) else [persons]})
The related part from the template:
<div class="jumbotron row">
<form>
<label>Alanyok szűrése</label>
<input id="filter" type="text" placeholder="Keresett alany">
</form>
</div>
<div class="row">
<div class="col-4">
<div class="list-group" id="list-tab" role="tablist">
{% for person in persons %}
<a class="list-group-item list-group-item-action" id="list-{{person.code}}" data-toggle="list" href="#" role="tab" aria-controls="{{person.code}}">{{person.code}}</a>
{% endfor %}
</div>
</div>
<div class="col-8">
<div class="visualisation content">
<div class="canvas_div">
<canvas id="Canvas1" width="540" height="250" style="border:1px solid #202020;">
</canvas>
</div>
</div>
</div>
</div>
The input field with filter id has a callback on keyup event which sends a request to django with the content of the input field which is used in the view for query.
Here is the callback:
$( "#filter" ).keyup(function() {
$.get("", {text: $('#filter').val()});
});
When I checked it with Pycharm debugger, the render returns the correct html but on the client side the html doesn't change. How to re-render with the new object list?
Take a part of your html code that you want to replace and place it inside a new html file like this:
new_html:
<div class="list-group" id="list-tab" role="tablist">
{% for person in persons %}
<a class="list-group-item list-group-item-action"
id="list-{{person.code}}" data-toggle="list"
href="#" role="tab" aria-controls="{{person.code}}">
{{person.code}}
</a>
{% endfor %}
</div>
now in your view replace the name of your old html file ( that you are rendering ) with the new html file like this:
return render(request, 'new_html.html',
{'persons': persons if not isinstance(persons,models.Person) else [persons]})
and now in your ajax you can dynamically load this new_html like this :
$( "#filter" ).keyup(function() {
$.get("",
{text: $('#filter').val()},
function(data){
$( "#list-tab" ).replaceWith( data );
}
);
});
You are not doing nothing with the returned data. Add a callback function in the get method call. You get the response from the server in the first argument. Use that to hide and show contents on the page. Or you can even replace elements in the DOM. See jquery.replaceWith.
$( "#filter" ).keyup(function() {
$.get("", {text: $('#filter').val()}, function(response){ });
});
I create a simply website about books. I display the title and description in books.html
<div id="book-container">
<p><h2>{{ b.title }}</h2></p>
<div><p>{{ b.description }}</p></div>
<br>
</div>
and my route file
#app.route('/show_books', methods=['GET', 'POST'])
def show_books():
books = Book.query.all()
return render_template('books.html', title='Home', books=books)
I have problem, because I want to display more information about book after clicking on title. What is the best way to do it? Thanks for help!
Ok, I find other solution but it doesnt work well:
book.html:
<div id="book-container">
{{ b.title }}
<div><p>{{ b.description }}</p></div>
<br>
</div>
routes.py:
#app.route('/detail_book/<title>')
def detail_book(title):
book = Book.query.filter_by(title=title).first_or_404()
return render_template('detail_book.html', book=book)
detail_book.html:
DETAILS
<div id="book-container">
{{ b.id }}
<h2>{{ b.title }}</h2>
<div><p>{{ b.description }}</p></div>
<br>
</div>
After clicking on title my url looks like:
http://localhost:5000/detail_book/Painted%20Man
And in consol: jinja2.exceptions.UndefinedError: 'b' is undefined
And I really have no idea how to solve this problem
You can use this to access the title you click. And this.id will give you the id of this element:
<div id="book-container">
<h2 id="{{ b.title}}" class="titles">{{ b.title }}</h2>
<div><p>{{ b.description }}</p></div>
<br>
</div>
<script type=text/javascript>
$(function(){
$('.titles').bind('click', function(){
alert(this.id);
});
});
</script>
By clicking on the title, you will see a modal indicating the id of the current element (in this case the id will be the title of the book).
The idea here is to add the class .titles to all the titles that will appear on your page and recover, with this.id, the id of the element you click. Then you can make an Ajax request to find the additional information corresponding to the specific element on which you clicked.
It looks like detail_book has a variable book not b.
In your render template you use the variable book.
Below is what the html should look like.
DETAILS
<div id="book-container">
{{ book.id }}
<h2>{{ book.title }}</h2>
<div><p>{{ book.description }}</p></div>
<br>
</div>
My web app currently has 3 pages. I obtained a user input on the first page, which I passed to my view.py, and calculated some variables I needed for my 2nd page. I want to pass the variables that exist in my 2nd page to the third page, but don't know how to go about it. Any suggestions on how to modify the html for the 2nd page to achieve this?
So far, I'm solving this problem by making my variables global in view.py. This seems to work but doesn't seem to be a viable long-term solution.
Thanks!
existing variables: thePrediction, theData
The html for the 2nd page:
<div class = "caption-full">
<h3>Currently, I have a {{thePercentage}} chance of getting adopted.</h3>
{% if thePrediction[1] + thePrediction[2] >0%}
<form action="/third_page" method="GET">
<button class="btn btn-large btn-info" >Go to third page</button>
</form>
{% endif %}
</div>
I think I figured it out:
<div class = "caption-full">
<h3>Currently, I have a {{thePercentage}} chance of getting adopted.</h3>
{% if thePrediction[1] + thePrediction[2] >0%}
<form action="/third_page" method="GET">
<input type="hidden" name="alignment" value="{{thePassedValue}}" />
<button class="btn btn-large btn-info" >Go to third page</button>
</form>
{% endif %}
</div>