django easy pdf can't display include static files (css/ images) - django

I am trying to include some images and css into my pdf using django-easy-pdf, however they aren't showing up.
getFile '/static/open-iconic/font/css/open-iconic-bootstrap.css' '...\\mysite\\__dummy__' '...\\mysite\\__dummy__'
Traceback (most recent call last):
File "...\Python\Python36-32\lib\site-packages\xhtml2pdf\context.py", line 828, in _getFileDeprecated
nv = self.pathCallback(name, relative)
File "...\Python\Python36-32\lib\site-packages\easy_pdf\rendering.py", line 35, in fetch_resources
path = os.path.join(settings.STATIC_ROOT, uri.replace(settings.STATIC_URL, ""))
File "...\Python\Python36-32\lib\ntpath.py", line 75, in join
path = os.fspath(path)
TypeError: expected str, bytes or os.PathLike object, not NoneType
line 0, msg: getFile %r %r %r, fragment:
My template file:
{% load static %}
<link href="{% static '/open-iconic/font/css/open-iconic-bootstrap.css' %}" rel="stylesheet">
my folder structure:
mysite
- mysite
- app
-static
The static files are working when serving normal webpages, but not in the pdf. Any suggestions?

From this Thread, Django-easy-pdf can render images from local file:// or remote http/https urls using WeasyPrint. This means you are going to edit your settings file for this setup to work in harmony with django-site. I modified demo app to illustrate this. clone/pull django-easy-pdf-demo-app
for the modified app.

Related

Accessing Goaccess report.html within 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."

CSS file being read as HTML file

I'm trying to link a css stylesheet to my django html template but it keeps being read as an html file with the error:
127.0.0.1/:1 Refused to apply style from 'http://127.0.0.1:8000/static_cdn/css/base-template.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
This is my base.html file and I know the path is correct because VS Code directs me to the file when I left-click on the link.
<head>
<link type="text/css" rel="stylesheet" href="../../static_cdn/css/base-template.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<title>GuitarShop</title>
</head>
Here is my directory:
Project Folder
guitarshop > templates > base.html
static_cdn > css > base-template.css
The reason why I am storing the css file in the static_cdn folder instead of a static folder in the templates folder is because when I do so, the command "python manage.py collectstatic" doesn't collect the file folder so I get the following error:
GET http://127.0.0.1:8000/static/base-template.css net::ERR_ABORTED 404 (Not Found)
Please help!
Have you pointed your "Static_URL" to static_cdn folder?

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')

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.

Django Appending Slashes to Static File URLs on OpenShift

I am attempting to deploy a Django 1.6 application on OpenShift using the Python 3.3 cartridge, but I have run into problems with static files. I have had partial success with the OpenShift IRC channel, tutorials/templates (for example), and previous StackExchange questions (for example), but nothing has completely resolved the problem.
When I request the static content by URL (e.g. 'mydomain.com/static/stylesheet.css' or 'mydomain.com/static/icons/cog.svg') I can see them perfectly fine. When static files are used as SVG data for icons, they show up fine. Only when linking to a stylesheet have I run into problems. I use the following to include CSS in my template:
<link type="text/css" rel="stylesheet" href={% static "stylesheet.css" %}/>
I have loaded the static files tag set with {% load staticfiles %}. Instead of seeing the stylesheet at /static/stylesheet.css, Django (I assume that it is Django, not Apache) looks for it at /static/stylesheet.css/ (note the trailing slash). This causes the request to fail with a 404 status code. The same thing occurs when I use other file extensions (I have tried .txt, .css, and .svg) or link to a file contained in a subdirectory of static. It is only in this circumstance that an extra trailing slash is appended.
It is my understanding that Django appends a trailing slash to a URL in the event that the URL does not match any of the patterns defined in urls.py. Is it possible on OpenShift to configure Apache so that it directly handles all requests to URLs of the form /static/*? I have an .htaccess file in the wsgi directory with the commands
Rewrite Engine On
Rewrite Rule ^application/static/(.+)$ /static/$1 [L]
but this does not solve the problem. I have also tried using a rewrite rule for just the stylesheet as well as a few things with Alias but have had no luck there, either.
Should Django be getting the requests for these static files at all? I have confirmed that DEBUG is being set to False in my settings.py file, and make no mention of django.views.static.serve in my urls.py file. Here are the relevant parts of settings.py:
STATIC_URL = '/static/'
if 'OPENSHIFT_REPO_DIR' in os.environ:
STATIC_ROOT = os.path.join(os.environ.get('OPENSHIFT_REPO_DIR'),
'wsgi', 'static')
else:
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
I do not set values for STATICFILES_DIRS or STATICFILES_FINDERS because at present I'm only dealing with static files found at STATIC_ROOT. The OpenShift project looks like
~/app-root/runtime/repo/wsgi/
.htaccess
application
openshift/
settings.py
manage.py
#And so on.
static/
stylesheet.css
icons/
cog.svg
#More icons here.
This is my first time trying to deploy and I am stuck on this stumbling block. Does anyone know what I am doing wrong?
Instead of href={% static "stylesheet.css" %}, try href="{% static 'stylesheet.css' %}"