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>
Related
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)
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>
`
I am using wtforms as part of a Python + Flask project. There are some cases where I want multiple fields of a form to appear on the same line on the webpage. With SelectField, this works as expected. However, when I use IntegerField, it seems to automatically create a new line after the field is displayed, and I get have more than one on a line.
The Form:
class PremiumMandatory(FlaskForm):
match_dol = IntegerField('Dollar')
match_per = IntegerField('Percent')
The .html
{{form.match_dol.label}}
${{form.match_dol(size=3)}}
 
{{form.match_per(size=3)}}%
{% for error in form.match_per.errors %}
Using the above, the two fields also appear on different lines on the webpage. Ho do I keep then on the same line?
This is an entirely HTML/CSS problem. There are many ways to put multiple fields of a form on the same line, for example, you could use Bootstrap's grid system, which is very easy to use.
Another simple way is:
<form>
<div style="display: table;">
<div style="display: table-row;">
<div style="display: table-cell;">
{{ form.match_dol.label }}
{{ form.match_dol(size=3) }}
</div>
<div style="display: table-cell;">
{{ form.match_per.label }}
{{ form.match_per(size=3) }}
</div>
</div>
<div style="display: table-row;">
...
</div>
</div>
</form>
I have been working on a project with Django on the back-end and amp on the front-end; although I am having some troubles to link both tags like the lightbox one.
I would like to get a list of first images on my product page (I have done it) and by clicking on an image it displays me the other images of that object on a lightbox without going to the detail template.
The whole project is updated on GitHub at:
https://github.com/lucasrf27/dealership
That is the amp code that I am trying to. I am trying this one on test.amp.html besides put on my category. (product template)
<body>
<h1>lucas</h1>
<div>
{% for v in veiculos %}
<h1>{{v.modelo}}</h1>
<amp-img lightbox="cars" src="{{ v.first_image.imagem.url }}" width="" height="" layout="fill" alt="{{v.modelo}}">
<amp-carousel lightbox="cars" width="350" height="350" type="slides">
<div>
{% for v in veiculos %}
<h1>{{v.modelo}}</h1>
<amp-img lightbox="cars" src="{{ v.first_image.imagem.url }}" width="300" height="400" alt="{{v.modelo}}">
<amp-carousel lightbox="cars" width="350" height="350" type="slides">
{% for p in veiculos.images.all %}
<amp-img lightbox="cars" src="{{p.imagem.url}}" width="" height="" layout="fill" alt="{{v.modelo}}"></amp-img>
{% endfor %}
</amp-carousel>
</amp-img>
{% endfor %}
</div>
</amp-carousel>
</amp-img>
{% endfor %}
</div>
<!-- These will belong to a different lightbox gallery -->
<div>
<amp-img lightbox="another" src="image3.jpg" width="400" height="300" layout="responsive"></amp-img>
<amp-img lightbox="another" src="image4.jpg" width="400" height="300" layout="responsive"></amp-img>
</div>
When I open the images from the lightbox on a new URL,
I get this one:
http://127.0.0.1:8000/veicles/image3.jpg (404)
However the image is in this one:
http://127.0.0.1:8000/media/veiculos_imagens/bugat-logo-whatsapp-fundo-transparente3.png
Is there some sort of media_prefix or something like that?
i've got the results in a silly way. besides setting on my views or my template a set up a object in function like i did in first_image but for the second and the other 2
it got like:
template
<body>
<h1>lucas</h1>
{% for v in veiculos %}
<amp-carousel lightbox width="1600" height="900" layout="responsive" type="slides">
<amp-img src="{{v.first_image.imagem.url}}" width="200" height="100"></amp-img>
<amp-img src="{{v.second_image.imagem.url}}" width="200" height="100"></amp-img>
</amp-carousel>
{% endfor %}
models:
def first_image(self):
return self.images.first()
def second_image(self):
return self.images.all()[1]
if anyone in the future is not understanding the project try to access:
https://github.com/lucasrf27/dealership
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){ });
});