Accessing Goaccess report.html within flask - flask

I have a website that uses flask and I would like to display the stats generated by goaccess from within my website.
in my route.py, I have added:
#main.route("/report")
def report():
return render_template('report.html')
and I have made sure the report.html is in the template forlder.
the problem is that I get the following error:
File "/templates/report.html", line 866, in template
<div class="grid-module {{#className}}{{className}}{{/className}}{{^className}}gray{{/className}}">
File "/lib/python3.6/site-packages/jinja2/environment.py", line 497, in _parse
return Parser(self, source, name, encode_filename(filename)).parse()
File "/lib/python3.6/site-packages/jinja2/parser.py", line 901, in parse
result = nodes.Template(self.subparse(), lineno=1)
File "/lib/python3.6/site-packages/jinja2/parser.py", line 874, in subparse
next(self.stream)
File "/lib/python3.6/site-packages/jinja2/lexer.py", line 359, in __next__
self.current = next(self._iter)
File "/lib/python3.6/site-packages/jinja2/lexer.py", line 562, in wrap
for lineno, token, value in stream:
File "/lib/python3.6/site-packages/jinja2/lexer.py", line 739, in tokeniter
name, filename)
jinja2.exceptions.TemplateSyntaxError: unexpected char '#' at 298804
Would anyone know how to solve this? I don't want to touch report.html and would like to use it as such.
If there is no solutions, can anyone suggest a way to access report.html from the internet?
Thank you.

What you want to do is serve a static file using flask. See How to serve static files in Flask
If you take a look at the docs the render_template function "Renders a template from the template folder with the given context". What you have is a complete, self-contained HTML file, and not a template. You could instad use the send_from_directory function. Do note that in production environment you probably do not want to serve file using Flask but instead use the web server (e.g. NGINX).
Example code:
from pathlib import Path
import os
...
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
TEMPLATES_DIR = os.path.join(APP_ROOT, 'templates')
#app.route("/report")
def report():
REPORT_FILE = os.path.join(TEMPLATES_DIR, "report.html")
if Path(REPORT_FILE).is_file():
return send_from_directory(REPORT_FILE_PATH, "report.html")
return "No stats."

Related

flask send_from_directory function keeps sending the same old file

I have a flask app that contains a link to download a file from the server. The file will be updated by another callback function. The part for send_from_directory is like this:
app = flask.Flask(__name__)
dash_app = dash.Dash(__name__,server=app,url_base_pathname="/",external_stylesheets=external_stylesheets)
...
#dash_app.server.route('/download/',methods=["GET","POST"])
def download_data():
return flask.send_from_directory("../data/",
filename='result.csv',
as_attachment=True,
attachment_filename='result.csv',
cache_timeout=0)
I have 2 problems:
1) the file downloaded are always the same old file, despite I have have set the cache timeout as 0.
2) the downloaded file are always named as "download", instead of the file name I specified "result.csv".

Django static files templatetags.static

I am trying to open a json file in python. It is in a directory called json in static directory of my app. I configured the static files as per the given documentation.
But I get this error on opening files in python using open() function
def send(request):
file = static('accounts/json/credentials.json')
f = open(file, "r")
return HttpResponse("click here <a href='" + file + "'> asd</a>")
The above code generates a FileNotFoundError
No such file or directory: '/static/accounts/json/credentials.json'
I also used this code
def send(request):
file = static('accounts/json/credentials.json')
return HttpResponse("click here <a href='" + file + "'> asd</a>")
The above code successfully gave me the response. And On clicking the link asd it is working fine and opens the JSON file.
I have googled a bit and also went through few stackoverflow questions but not sure what the actual error is, Can anyone help me in finding out.
Thanks
Presuming static is the helper function from the static templatetags, it gives you the URL path to STATIC_URL. It doesn't give you the file path. That is set in STATIC_ROOT and you will need to join it yourself:
path = os.path.join(settings.STATIC_ROOT, 'accounts/json/credentials.json')
f = open(path, r)
Note though it doesn't make sense to to try and put this file into the text of a link; your second snippet is correct if you want to do that.
In your settings.py file there should be a variable called BASE_DIR defined. You need to prepend that on your file name. Something like:
file = static(settings.BASE_DIR + '/accounts/json/credentials.json')

sqlalchemy showing an error related to os.getenv()

I am working on sqlalchemy and there's command in it engine -
create_engine(os.getenv("DATABASE_URL")).
When I run the program it shows an error saying -
"Could not parse rfc1738 URL from string 'C:\Program Files\ PostgreSQL\10\data"
Code
import os
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
#engine = create_engine('sqlite://')
engine = create_engine(os.getenv("DATABASE_URL"))
db = scoped_session(sessionmaker(bind=engine))
def main():
flights = db.execute("SELECT origin, destinaiton, duration FROM flights").fetchall()
for flights in flights:
print(f"{flight.origin} to {flight.destination}, {flight.duration} minutes.")
if __name__ == "__main__":
main()
Error
Traceback (most recent call last): File "list.py", line 7, in
engine = create_engine(os.getenv("DATABASE_URL")) File "C:\Users\Amber
Bhanarkar\AppData\Local\Programs\Python\Python36\lib\site-packages\sqlalchemy\engine__init__.py",
line 424, in create_engine
return strategy.create(*args, **kwargs) File "C:\Users\Amber Bhanarkar\AppData\Local\Programs\Python\Python36\lib\site-packages\sqlalchemy\engine\strategies.py",
line 50, in create
u = url.make_url(name_or_url) File "C:\Users\Amber Bhanarkar\AppData\Local\Programs\Python\Python36\lib\site-packages\sqlalchemy\engine\url.py",
line 211, in make_url
return _parse_rfc1738_args(name_or_url) File "C:\Users\Amber Bhanarkar\AppData\Local\Programs\Python\Python36\lib\site-packages\sqlalchemy\engine\url.py",
line 270, in _parse_rfc1738_args
"Could not parse rfc1738 URL from string '%s'" % name) sqlalchemy.exc.ArgumentError: Could not parse rfc1738 URL from string
'C:\Program Files\PostgreSQL\10\data'
Please someone help me resolving this issue.
The engine URL shouldn't be a path to your local Postgres installation but a sting that tells SQLAlchemy how to connect to the database. It has the following format:
postgresql://username:password#server:port/databasename
I'm also watching course video of cs50 now. You should try to just use create_engine("your_database_url").
If you still want to use create_engine(os.getenv("DATABASE_URL")) tp process, make sure you can log in using the command line like this psql $DATABASE_URL.
using psql $DATABASE_URL works for me but I'm still getting the same error on create_engine("your_database_url")
(project1) C:\Users\Gregory Goufan\Downloads\CS50s Web Programming with Python and JavaScript\project1\project1\project1>psql postgresql://openpg:openpgpwd#localhost:5432/postgres
psql (9.5.8)
WARNING: Console code page (437) differs from Windows code page (1252)
8-bit characters might not work correctly. See psql reference
page "Notes for Windows users" for details.
Type "help" for help.
postgres=#
But it is true that by putting the url direct in create_engine funciton works strange thing because it is indeed a string which is returned
sqlalchemy.exc.ArgumentError: Could not parse rfc1738 URL from string ' 'postgresql://openpg:openpgpwd#localhost:5432/postgres''

Flask Security - TemplateAssertionError: no filter named 'urlencode'

I just added flask-security to my flask project. It works locally, but reports this error on OpenShift:
TemplateAssertionError: no filter named 'urlencode'
I don't know if it is some wrong library version, or how to debug this. This is my setup.py package list:
install_requires=['Flask==0.10.1',
'SQLAlchemy==0.9.8',
'Flask-SQLAlchemy==2.0',
'Flask-Security==1.7.4',
'Werkzeug==0.9.5',
'blinker==1.3',
'Flask-Login==0.2.11',
'Flask-Mail==0.9.1',
'Flask-Principal==0.4.0',
'Flask-Script==2.0.5',
'Flask-WTF==0.10.3',
'itsdangerous==0.24',
'passlib==1.6.2'
]
The urlencode filter was added to jinja in v2.7. But GAE only supports v2.6. Changing the version to "latest" in my app.yaml still runs with 2.6 (notice the python27_lib/versions/third_party/jinja2-2.6/jinja2/environment.py path):
...
File "/base/data/home/apps/s~healthier-staging/1.386037228785871893/lib/flask/templating.py", line 128, in render_template
context, ctx.app)
File "/base/data/home/apps/s~healthier-staging/1.386037228785871893/lib/flask/templating.py", line 110, in _render
rv = template.render(context)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/jinja2-2.6/jinja2/environment.py", line 894, in render
return self.environment.handle_exception(exc_info, True)
File "/base/data/home/apps/s~healthier-staging/1.386037228785871893/lib/flask_security/templates/security/_menu.html", line 4, in template
<li>Login</li>
TemplateAssertionError: no filter named 'urlencode'`
I fixed this by adding a simple filter (copying the code that was added to jinja) manually:
def do_urlescape(value):
"""Escape for use in URLs."""
return urllib.quote(value.encode('utf8'))
app.jinja_env.globals['urlencode'] = do_urlescape
I have solved this, by doing 'pip freeze' on my local machine, and copying libraries to setup.py one by one. Though I'm still not sure which one produced an error, probably wrong version of jinja2.

test function with Google App Engine `files` api

I have a function that uses the Google Blobstore API, and here's a degenerate case:
#!/usr/bin/python
from google.appengine.ext import testbed
def foo():
from google.appengine.api import files
blob_filename = files.blobstore.create(mime_type='text/plain')
with files.open(blob_filename, 'a') as googfile:
googfile.write("Test data")
files.finalize(blob_filename)
tb = testbed.Testbed()
tb.activate()
tb.init_blobstore_stub()
foo() # in reality, I'm a function called from a 'faux client'
# in a unittest testcase.
The error this generates is:
Traceback (most recent call last):
File "e.py", line 18, in
foo() # in reality, I'm a function called from a 'faux client'
File "e.py", line 8, in foo
blob_filename = files.blobstore.create(mime_type='text/plain')
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/files/blobstore.py", line 68, in create
return files._create(_BLOBSTORE_FILESYSTEM, params=params)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/files/file.py", line 491, in _create
_make_call('Create', request, response)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/files/file.py", line 230, in _make_call
rpc = _create_rpc(deadline=deadline)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/files/file.py", line 213, in _create_rpc
return apiproxy_stub_map.UserRPC('file', deadline)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 393, in __init__
self.__rpc = CreateRPC(service, stubmap)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 67, in CreateRPC
assert stub, 'No api proxy found for service "%s"' % service
AssertionError: No api proxy found for service "file"
I don't want to have to modify foo in order to be able to test it. Is there a way to make foo work as expected (i.e. create the given file) in Google App Engine's unit tests?
I would expect to be able to do this with Google's API Proxy, but I don't understand it well enough to figure it out on my own.
I'd be grateful for your thoughts and suggestions.
Thanks for reading.
It seems like testbed.init_blobstore_stub() is outdated, because dev_appserver inits blobstore stubs differently. Here is my implementation of init_blobstore_stub that allows you to write to and read from blobstore in your tests.
from google.appengine.ext import testbed
from google.appengine.api.blobstore import blobstore_stub, file_blob_storage
from google.appengine.api.files import file_service_stub
class TestbedWithFiles(testbed.Testbed):
def init_blobstore_stub(self):
blob_storage = file_blob_storage.FileBlobStorage('/tmp/testbed.blobstore',
testbed.DEFAULT_APP_ID)
blob_stub = blobstore_stub.BlobstoreServiceStub(blob_storage)
file_stub = file_service_stub.FileServiceStub(blob_storage)
self._register_stub('blobstore', blob_stub)
self._register_stub('file', file_stub)
# Your code...
def foo():
from google.appengine.api import files
blob_filename = files.blobstore.create(mime_type='text/plain')
with files.open(blob_filename, 'a') as googfile:
googfile.write("Test data")
files.finalize(blob_filename)
tb = TestbedWithFiles()
tb.activate()
tb.init_blobstore_stub()
foo()
I don't know if it was added later to the SDK, but using Testbed.init_files_stub should fix it:
tb = testbed.Testbed()
tb.activate()
tb.init_blobstore_stub()
tb.init_files_stub()
Any chance that you are trying to do this using the gaeunit.py test runner? I see the same error while using that, since it does it's own code to replace the api proxy.
The error disappears when I added 'file' to the "as-is" list of proxies in the _run_test_suite function of gaeunit.py.
Honestly, I'm not sure that the gaeunit.py proxy replacement code is needed at all since I'm also using the more recently recommended testbed code in the test cases as per http://code.google.com/appengine/docs/python/tools/localunittesting.html. So, at this point I've commented it all out of gaeunit.py, which also seems to be working.
Note that I'm doing all this on a dev server only, in highly experimental mode on python27 in GAE with Python 2.7.
Hope this helps.