Flask runs python script with "OnClick": False positive activation - python

In my app.py I added a python fuction (to track events) like this:
app = flask.Flask(__name__)
app.jinja_env.globals.update(track_event=track_event)
def track_event(category, label, action):
do="something"
In my HTML code I added it like this:
<a href="somewebsite.web"
class="button button-rounded tright button-large topmargin-sm"
onclick="{{ track_event(category='outbound',action='stackoverflow',
label='somewebsite.web') }}"
>
On this side I offer a listing and therefore add this kind of HTML snipped several times with different URLS (instead of somewebsite.web).
Here is my problem: Instead of being activated "onclick", everytime I load the website all of the onclick events are immediately activated once the browser finished loading.
The functions works as expected, but it shouldnt be called unless someone actually clicks on the . Did anyone have a similar experience?
Is my error in Python or HTML?

In a comment you mentioned that, in the rendered HTML, you had onclick="None". The problem is that your function
def track_event(category, label, action):
do="something"
doesn't return anything. Jinja is going to do what you tell it to do and put the return value of that function in the template. If you return None (which is implicit: if you never explicitly return, you return None by default).

Related

Flask: code inside a #app.route fails (runs forever) when called a second time

I have some Python metapy code being executed inside a Flask route which runs perfectly fine when the route is called the first time (ie a user submits a form after startup of the application) but it doesnt terminate when it runs a second time (ie the form is submitted a second time after application startup).
Precisely:
#app.route('/search', methods=['POST'])
def searchPageResults():
form = SearchForm(request.form)
import metapy
idx = metapy.index.make_inverted_index(os.path.abspath("search/config.toml"))
ranker = metapy.index.OkapiBM25()
query = metapy.index.Document()
query.content("auto")
for result in ranker.score(idx, query):
print(result)
return render_template('SearchPage.html', form=form)
The code snippet inside the method runs fine if I run it outside Flask (no matter how many times I call it). Only inside the method decorated with #app.route(...) it seems to only run once. To be specific: the ranker.score(...) function is the one running forever.
Since the code runs fine outside flask, I think there is something Flask specific happening in the background I don't understand.
What I tried so far (but didn't help):
When I have the "import metapy" statement at the top of the file,
then even the first call to ranker.score(...) runs forever.
I ensured that "import metapy" and the initialization of "idx" and "ranker" only run once by putting the search functionality inside an own Class
which is instantiated at Flask server startup. However, also then the
code won't run even at the first call of the route.
Is there something Flask specific explaining this behaviour?
----Update: additional info-----
config.toml
index = "idx"
corpus = "line.toml"
dataset = "data"
prefix = "."
stop-words = "search/german-stopwords.txt"
start-exceptions = "search/sentence-start-exceptions.txt"
end-exceptions = "search/sentence-end-exceptions.txt"
function-words = "search/function-words.txt"
punctuation = "search/sentence-punctuation.txt"
[[analyzers]]
method = "ngram-word"
ngram = 1
filter = [{type = "icu-tokenizer"}, {type = "lowercase"}]
As said, the behaviour only occurs after the second call of this Flask route. Locally everything works fine (with exact same dataset and config.toml)
Update: same behaviour in MetaPy Flask demo app
I have the same behaviour in the MetaPy demo app: https://github.com/meta-toolkit/metapy-demos. (Only difference is that I needed to take some newer versions as specified in the requirements.txt for some packages due to availability).
Solved. There was a problem with the Flask integrated Webserver. Once deployed to another webserver, the problem was solved.

How can I have Django generate or change a DOM element?

I'm building a Django app and I would like to have a view/function add a line of html to the inner html of a specific div element with an id every time it is run.
I know how to do this with Javascript but then I would need the view to run that script every time it runs.
Is there a way to do this in the Python document?
The title of your question asks about creating a DOM Element in python. In order to do so, inside your views.py
from django.template import Context, Template
def in_some_view(request):
template = Template('<div class="new-dom-element">Element</div>')
'''
You can create elements above. You can even give it Context Variables
For example: template = Template('<div class="new-dom-element">{{ context_variable }}</div>')
'''
context = Context({'context_variable': your_python_variable})
#By sending the context variable "your_python_variable", you can do anything iteratively.
dom_element = template.render(context)
#Now you can return this dom_element as an HttpResponse to your Javascript.
#Rest of your code.
return HttpResponse(dom_element)
Note: I answered this keeping in mind that you don't want to take a way outside the domain of AJAX requests. If so, then it's really difficult to bring and append some data if an HTML is already displayed on the browser screen. That's exactly why AJAX was created in the first place.
Hope this helps. Thanks.

How to redirect from one view to another?

I have an x view that redirects me to some_name.html page.
This view needs to create a class that it is importing from other python file.
This view calls a specific function (algorithm) that has some logic in it.
lets say this func return a dictionary.
I want that view 'x' will redirect me to negotioate.html page with this dynamic return dictionary.
When the user gets the output he should choose from 3 options and basically trigger the algorithm again.
Meaning, I want in each of those trigger to display the user the algo output but without reidrecting me to other page, but refreshing the current one.
Try :
url(r'^(?P<object_id>\d+)/$', edit, name="edit"),
OR
Return :
return redirect('quizzes.views.quizView', quizNumber=quizNumber)
Hi you can redirect from one view to another with data.
Try this code which I am using for my project also.
def notification_view(request,pk):
notification_to_edit=notifications.objects.get(pk=pk)
notification_to_edit.viewed = True
notification_to_edit.save()
return HttpResponseRedirect(reverse('taskdetail',kwargs={'pk':notification_to_edit.task_id.id}))
You need to use AJAX method to avoid page refresh. This view will reload the page, but code should work fine.

loadhook function in web.py not working

I was trying to experiment with the loadhook function in web.py, however I am not quite able to make it work. Here is my code:
import web
render = web.template.render('templates/')
urls = (
'/(.*)', 'index'
)
class index:
def GET(self, name):
return render.base(name)
def test():
print "damn"
render.base("test")
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
app.add_processor(web.loadhook(test))
The base.html template is pretty simple which echoes back the "name" parameter.
What I understood from the documentation was that the loadhook function will be called before every request. But it doesn't seem to work. I have tried going to the homepage, another page etc. Neither do I see a print statement on my CMD, nor does the base template with the name test gets executed.
I tried running the same code with just the add_processor as well, but no luck.
Can anyone help me figure out how to run a function before a request happens on a page?
Also, I am assuming request only encompasses browser level requests. Is there any way to capture more via web.py? (such as call a function on keypress, mouse click etc.)
Any help is much appreciated!
loadhooks are called early in the processing and are used to either set configuration or intercept. For example, I implement a black list similar to the following:
def my_hook():
# If requester's IP is in my blacklist, redirect his browser.
if blacklist.in_blacklist(web.ctx.ip) and web.ctx.path != '/blacklist':
raise web.seeother('/blacklist')
....
app.add_processor(web.loadhook(my_hook))
In your example, your test hook calls render (I'm guessing you're trying to render the test page?) Problem is loadhooks don't return data to the browser, so calling render here doesn't do what you want.
Couple other issues: you need to call app.add_processor(web.loadhook(my_hook)) prior to calling app.run(), because the latter sets your polling loop & never returns.
As for your final question: to capture keypresses, etc. you need your javascript to send something to the server.... Everytime there's a keypress, do an ajax call to the server to log the action.
Python's powerful, but still can't read minds.

Setting cookies for static files using bottle.py

New to python. I am using bottle.py as a web server.
I have a set of static HTML files that need to be rendered on different routes. I am using static_file() function for the same. I also want to set a session based cookie for the page. SO I am using response.set_cookie().
But it turns out that when I am returning a static_file the cookie is never set. However if I change the response to a simple string, set_cookie() works fine. Can anyone explain why? And how can I fix this?
#app.route("/index")
def landingPage():
response.set_cookie("bigUId", "uid12345")
# return "Hello there"
return static_file("/html/index.html", root=config.path_configs['webapp_path'])
Welcome to Bottle and to Python. :)
Looking at the Bottle source code, the problem is readily apparent. Look how static_file ends:
def static_file(...):
...
return HTTPResponse(body, **headers)
static_file creates a new HTTPResponse object--so any headers you've set before then will be discarded.
A very simple way around this is to set the cookies after you call static_file, like this:
#app.route("/index")
def landingPage():
resp = static_file("/html/index.html", root=config.path_configs["webapp_path"])
resp.set_cookie("bigUId", "uid12345")
return resp
I just tried it, and it works perfectly. Good luck!
Well, I just tried, indeed it's not working, I never tried to use cookie with a static_file() before ... However, you can do the following to return a static file as a template, and the cookie will be set :
Your routing function :
#route('/test')
def cookie_test():
response.set_cookie("test", "Yeah")
return template('template/test.html')
And for this to work, you'll need to define a route for /template this way :
#route('/template/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root="./template")
(Obviously, change "/template" to whatever you need according to your project path !)
I'm doing it this way, and it's working fine ! I'm not sure why it doesn't work when you try to set a cookie with static_file(), it might come from the fact that IT IS a static file that you're serving, or whatever, I really don't know.
Also, using the template() function in order to server a "static" html page might not be the right way to do it, but I'm personnaly doing it since a while, and I've never had any issue with this.
Hope it helps !

Categories

Resources