Flask with sqlalchemy how can i highlight my searched query results? - python

I am making my app in which I'm querying my data base with like search and what I wanna do is to highlight the results which are showing in my result template. My search route looks like this:
#app.route("/post")
def post():
term = request.args.get("search_text", None)
if term == None:
scanned = Images.query.filter_by().all()[0:15]
return render_template('post.html', scanned=scanned)
else:
term = request.args.get("search_text")
search = "%{}%".format(term)
scanned = Images.query.filter(or_(Images.content.like(search),Images.title.like(search)))
return render_template('post.html', scanned=scanned)
this my template file post.html
{% for scanned in scanned %}
<div class="post-preview">
<a href="/post2/{{scanned.Slug}}">
<h2 class="post-title">{{ scanned.title }}
</h2>
</a>
<p class="Images-meta">Posted by
Admin
on {{scanned.Date}}</p>
</div>
{{scanned.content[0:120]}}...
<hr>
</li></a>
{% endfor %}
now everything is working fine but I just want to highlight my search query in results template.

You write the template 'post.html'. You need to modify that html file to change how things are displayed.

Related

Flask: Make Application State Persist over tabs

I'm new to Flask and am trying to create an application that can remotely control a voltage supply to set voltage/current and turn the voltage supply on and off on and off. With these actions, I would like to update some info on the webpage.
The issue I'm running into is, if, for example, I set the power/current, I see the stats show up on the web page in the current table I'm in. But if I copy the same URL into another tab, I do not see the stats. Is there a way to show the stats on all web pages?
Below is a snippet from my server.py. I think it has something to do with the return values and what I'm rendering upon return, but I'm not sure now to fix this.
#application.route('/set-power-current', methods=["GET", "POST"])
def set_power_current():
if request.method == "POST":
req = request.form
ip = req["ip"]
serial = req["serial"]
power = req["power"]
current = req["current"]
channel = req["channel"]
set_power_current_channel(ip, serial, power, current, channel)
feedback = {"Power": power,
"Current":current,
"Channel":channel
}
if int(channel) == 1:
return render_template('index_server.html', data1=feedback)
if int(channel) == 2:
return render_template('index_server.html', data2=feedback)
if int(channel) == 3:
return render_template('index_server.html', data3=feedback)
return redirect(request.url)
return render_template('index_server.html')
Here is a snippet from my index_server.html to post the stats
<h2>Channel Stats</h2>
<div class="row">
<div class="column" style="background-color:#aaa;">
<h2>Channel 1</h2>
<ul>
{% if data1 %}
<li>Power: {{data1.Power}}</li>
<li>Current: {{data1.Current}}</li>
{% endif %}
</ul>
</div>
<div class="column" style="background-color:#bbb;">
<h2>Channel 2</h2>
<ul>
{% if data2 %}
<li>Power: {{data2.Power}}</li>
<li>Current: {{data2.Current}}</li>
{% endif %}
</ul>
</div>
<div class="column" style="background-color:#ccc;">
<h2>Channel 3</h2>
<ul>
{% if data3 %}
<li>Power: {{data3.Power}}</li>
<li>Current: {{data3.Current}}</li>
{% endif %}
</ul>
</div>
</div>
Here is what the current tab looks like after setting the values in Channel 3, for example:
Here is what a new tab looks like after I set the values:
I would like to find a way for both tabs to look the same after values are set.
Thanks!
If you want the stats to show on multiple pages, you should store them and not only display them.
You can easily make use of a database like SQLAlchemy to store the statistics and retrieve them after. It will then be consistent across all tabs/ pages.

How to call a function/method on Flask from the template

First of all, I'm quite new using flask, but this is something I haven't been able to find so far.
I'm working on my website with Flask and Jinja templates, using postgresql as a DB, I want to be able to call another function/method in my template.
Here I can get all my shares (posts)
#shares_app.route('/shares', methods=['GET'])
#login_required
def last_shares():
shares = fetch_last_shares()
form = ReusableForm(request.form)
return render_template('shares.html', form=form, shares=shares)
template
{% for share in shares %}
<li class="comment" style="border:1px solid black; padding:5px;" >
<a class="pull-left" href="#">
<img width="35" height="35" avatar="{{share[5]}}">
</a>
<div class="comment-body">
<div class="comment-heading">
<h4 class="user">{{share[5]}} ({{share[4]}}) </h4>
<h5 class="time">{{share[3]}} /</h5>
</div>
<p> <b>{{share[0]}} </b> / {{share[2]}}</p>
</div>
<!--comments here -->
Here I wanna be able to get all my comments related to shares, here its where I\'m no sure if I can call another function from my controller.
comments = fetch_last_comments(share[0])
{% for comment in comments %}
Show comments here
{% endfor %}
<!--comments here -->
{% endfor %}
Basically, I want to be calling this function
def fetch_comments_by_shares(share_id):
comments = db.query("""SELECT * FROM comments WHERE share_id = {} """.format(share_id)).getresult()
return comments
Thanks a lot.
Instead of making multiple DB queries for each and every share id you can get all the comments for all the shares in the backend and then pass comments while rendering the template.
like.
render_template('shares.html', form=form, shares=shares, comments=comments)
and if still, you want to call the python function from jinja template then you can follow this answer for the same.
Call a python function from jinja2

How to access variables within html template url_for

I'm building a Netflix like website for my Devops course. I made a Python list of dictionaries (Mockfilms) to define my films, and want to populate a database (Ratings) with reviews in preparation for sending data in the format :filmid: :userid: :rating: to a recommendation engine.
My index page is a list of film images with a link to a review form under each one. I want each review form to appear on a different url (/review/ID where ID is saved in mockfilms as oid). In order to do this I want to access mockfilms.oid, then pass it to the view function to make the url for the form. Once the form is complete I then want to add this ID to the Ratings database. Here is what I have so far:
Index:
{% extends "base.html" %}
{% block content %}
<h1>Hello, {{ current_user.username }}! Welcome to our extensive video library:</h1>
{% for film in mockfilms %}
{% set ID = film.oid %}
<div>
<a href = {{ film.video }}>
<img src = {{ film.image }} alt = "doh" style = "width:200px;height:200px;border:0;">
</a>
</div>
<div>
">Leave a review here!
{% endfor %}
{% endblock %}
Route:
#app.route('/review/<ID>', methods = ['GET', 'POST'])
#login_required
def review(ID):
form = ReviewForm()
if form.validate_on_submit():
review = Ratings(User_id = current_user.id, Score_given = form.score.data, Film_id = ID)
db.session.add(review)
db.session.commit()
flash('Thanks for your review')
return redirect(url_for('index'))
return render_template('review.html', title='Review Page', form=form)
The following error is what I get when I run it:
File "/home/jc/Desktop/Lokal/DevopsAssig/microblog/Kilfinnan/lib/python3.5/site-packages/werkzeug/routing.py", line 1768, in build
raise BuildError(endpoint, values, method, self)
werkzeug.routing.BuildError: Could not build url for endpoint 'review'. Did you forget to specify values ['ID']?
From this I assume that the issue is with the ID variable within this template. My searchings and learnings led me to believe that {% set %} in the index template would let me declare the ID variable and then use it in the dynamic.
Try this:
{% block content %}
<h1>
Hello, {{ current_user.username }}!
Welcome to our extensive video library:
</h1>
{% for film in mockfilms %}
<div>
<a href="{{ film.video }}">
<img src="{{ film.image }}" alt="doh" style="width:200px;height:200px;border:0;" />
</a>
</div>
<div>
<a href="{{ url_for('review', ID=film.oid) }}">
Leave a review here!
</a>
</div>
{% endfor %}
{% endblock %}
Ultimately your solution was quite close, but it is not necessary to use the Jinja set command when you need to pass the variable into url_for() function using the keyword for the parameter. You could still do it using {% set ID = film.oid %} but it would be a bit superfluous.
Try to provide key=value arguments into your url_for function.
Something like this
">Leave a review here!
Also Flask have a great documentation, Flask docs

"TemplateSyntaxError: Invalid filter:"; custom django template filter based on django docs broken, but template tags working

I have a template filter based on the django docs at https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/. For the life of me I can't see any difference in my usage and theirs, and am slowly going insane. I have a working tag I got on a forum as such:
myproject/index/templatetags/add_get_parameter.py:
from django.template import Library, Node, resolve_variable
register = Library()
class AddGetParameter(Node):
def __init__(self, values):
self.values = values
def render(self, context):
req = resolve_variable('request', context)
params = req.GET.copy()
for key, value in self.values.items():
params[key] = value.resolve(context)
return '?%s' % params.urlencode()
#register.tag
def add_get(parser, token):
pairs = token.split_contents()[1:]
values = {}
for pair in pairs:
s = pair.split('=', 1)
values[s[0]] = parser.compile_filter(s[1])
return AddGetParameter(values)
This one, add_get on lines 8-9, works, whereas shorten_title on line 4 doesn't work:
myproject/templates/index/silo.html:
{% load bootstrap add_get_parameter extras %}
...other stuff...
{% for article in articles %}
<div class="col-md-4 article-link">
<div class="panel panel-default hover">
<div class="panel-heading"><h4 class="url-link">{{ article.title|shorten_title }}</h4></div>
<div class="panel-body">
<p> <span class="url-text">{{ article.url }}</span></p>
<div class="article_button">Edit</div>
<div class="article_button"><p>Archive</p></div>
<div class="article_button">Delete</div>
<div style="margin-top:8px;">
{% for tag in article.tags.all %}
<p class="tag">{{ tag.name }}</p>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
Here's the villian:
from django.template import Library
register = Library()
#register.filter
def shorten_title(title):
length = len(title)
new = title
if length > 65:
new = title[0:65] + "..."
return new
register.filter('shorten_title', shorten_title)
He's been so rude I double registered him, just to see what happens (he doesn't work registered once as a decorator or afterward, and doesn't work registered twice).
{{ article.title }} works, but {{ article.title|shorten_title }} breaks the page with:
django.template.base.TemplateSyntaxError
TemplateSyntaxError: Invalid filter: 'shorten_title'
'Index' is definitely registered and working, and the page works when I delete the filter from that article.title tag.
Usually when I get a stubborn error I missed something small, but following the docs word for word has me baffled (I've written several working filters before). Is this filter bad, or is there maybe something else in my page that causes the issue? Thanks
You need to make sure you import the file with register.filter('shorten_title', shorten_title) before you render the template. Since that call happens outside of any functions it is run when you import the module. This has the side effect of registering it so that it will be available in your templates afterwards.

how to render only part of html with data using django

I am using ajax to sort the data which came from search results.
Now I am wondering whether it is possible to render just some part of html so that i can load this way:
$('#result').html(' ').load('/sort/?sortid=' + sortid);
I am doing this but I am getting the whole html page as response and it is appending the whole html page to the existing page which is terrible.
this is my views.py
def sort(request):
sortid = request.GET.get('sortid')
ratings = Bewertung.objects.order_by(sortid)
locations = Location.objects.filter(locations_bewertung__in=ratings)
return render_to_response('result-page.html',{'locs':locations},context_instance=RequestContext(request))
how can I render only that <div id="result"> </div> from my view function? or what am I doing here wrong?
From what I understand you want to treat the same view in a different way if you receive an ajax request.
I would suggest splitting your result-page.html into two templates, one that contains only the div that you want, and one that contains everything else and includes the other template (see django's include tag).
In your view then you can do something like the following:
def sort(request):
sortid = request.GET.get('sortid')
ratings = Bewertung.objects.order_by(sortid)
locations = Location.objects.filter(locations_bewertung__in=ratings)
if request.is_ajax():
template = 'partial-results.html'
else:
template = 'result-page.html'
return render_to_response(template, {'locs':locations},context_instance=RequestContext(request))
results-page.html:
<html>
<div> blah blah</div>
<div id="results">
{% include "partial-results.html" %}
</div>
<div> some more stuff </div>
</html>
partial-results.html:
{% for location in locs %}
{{ location }}
{% endfor %}

Categories

Resources