How to properly configure route to show only subdirectories? - flask

I am unable to download a csv from sub-directory but I can do it from a home directory.
I've tried changing routes to the subdirectory, but it throws 404 error.
#app.route('/', defaults={'req_path': 'Categorized%20Output/2019-06-27'})
#app.route('/<path:req_path>')
def index(req_path):
# data = dataset.html
#return dataset.html
folderLocation = os.path.dirname(__file__)
print(folderLocation)
abs_path = os.path.join(folderLocation,req_path)
print(abs_path)
# Return 404 if path doesn't exist
if not os.path.exists(abs_path):
return abort(404)
# Check if path is a file and serve
if os.path.isfile(abs_path):
return send_file(abs_path)
# Show directory contents
files = os.listdir(abs_path)
return render_template('index.html',files = files)
if __name__ == "__main__":
app.run()
My CSV's are located in multiple subfolder named as different dates in FolderLocation/Categorized Output/lot's of dates folder/
The index.html file from templates
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/style.css') }}"/>
<title>Show CSV</title>
</head>
<body>
<div class="table">
<ul>
{% for file in files %}
<li>{{ file }}</li>
{% endfor %}
</ul>
</div>
</body>
I want to be able to download CSV's from all different dates subfolder.
An example of the location of CSV's is: "127.0.0.1:5000/Categorized%20Output/2019-06-27"

I found a convenient way to grab a file/directory recently by using easygui.
pip install easygui
import easygui
#app.route('/')
def index():
get_a_file = easygui.fileopenbox()
files = get_a_file # do some stuff with your file
return render_template('index.html', files=files)
This answer doesn't address the root of your issue, but if it helps and you're interested you can read the easygui documentation.
if you want to start with a specific directory you can customize fileopenbox such as..
files = easygui.fileopenbox(
msg='some message',
title='some title',
default='c:\some_directory\some_directory\*.file_type',
filetype='*.file_type'
)
where file_type is any type of file.. .txt, .dat, etc.,

Related

Why is Django template not responding to static files?

It is exactly how it sounds. My main goal is to make the css file work with django template so I can design my templates.
Yesterday I tried and initially my folder structure was wrong. I placed static folder in myapp folder. Didn't work. I tried putting it in templates folder. It only worked when I had 2 static folders both in myapp and templates folder. Realized it isn't a working solution.
I placed a single static folder with a css file in it in mysite folder, at the same level with myapp folder and everything seemed to work. Satisfied I left at that.
Today I came back to it and it stopped working. It seems to be frozen. Not responding to the new codes. Old colors are showing but new colors aren't, which is odd. Tried changing the old colors, it won't change. Literally my css file has a class name .intro where I changed the color from purple to red, my template still showing purple which I set yesterday.
My template shows no error and all the texts and divs I am adding are updating with no issue.Kind of lost where I may have gone wrong. Certainly don't want to work with 2/3 same css file and static folder if I can help it.
Here are some codes.
My folder structure-
Everytime I update the css and refresh the template my console is showing some kind of error, here they are-
Settings.py file seems correct. Here is the relevant part-
import os
SETTINGS_PATH = os.path.dirname(os.path.dirname(__file__))
...
...
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
STATIC_ROOT= os.path.join(BASE_DIR, 'staticfiles')
my base.html -
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="{% static 'ok.css' %}"/>
</head>
<body>
{% block content %}
<h2 class="ok">This is a test</h2>
<div class="solved">This took a while!</div>
<div class="container">Didn't work on the other site!</div>
{% endblock content %}
</body>
</html>
and test.html -
{% extends "myapp/base.html" %}
{% block content %}
<h2 class="again">Content for My App</h2>
<p class="intro">Stuff etc etc.</p>
<p class="ok">write some more</p>
<div class="container">This should work</div>
{% endblock %}
URLs.py even though I think I am doing ok there -
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('base/', views.ok, name='base'),
path('test/', views.test, name='test')
]
And finally views.py , another page I don't think have any issues -
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
context = {}
return render(request, 'myapp/index.html')
def ok(request):
return render(request, 'myapp/base.html')
def test(request):
return render(request, 'myapp/test.html')
If you can spot anything kindly let me know. Any help is appreciated. Thanks.

using Flask Mail to send the rendered form

I am using flask_mail to send emails, while this works for text message, I need some help if i need to send a template itself (what does this mean: so I am rendering a report that contains multiple tables and a text area on the top with a submit button, once the user fills the text area and click on submit, I need flask to send the report containing table along with text data ).
This code fetches data from service now incident table
def incident():
service_now_url = SERVICE_NOW_URL
request_str = req
user = 'username'
pwd = 'password'
url = service_now_url + request_str
headers = {"Accept": "application/json"}
response = requests.get(url, auth=(user, pwd), headers=headers)
json_str = response.json()
records = json_str['result']
return records
This code below is used for rendering the text field and the table.
#app.route('/submit', methods=['GET','POST'])
def submit():
rec = incident()
form = Description(request.form)
shift = form.Shift.data
return render_template('index.html', rec=rec, state=STATES, form=form)
So for sending the email so far, I have written the function below, this sends an email but with table header only and no data.
def send_email(shift):
msg = Message(subject=shift ,recipients=['user#gmail.com'])
msg.html=render_template('index.html')
mail.send(msg)
I am not a Flask expert and still, in the learning phase, any help would be greatly appreciated.
#George thanks for your help, but this is not working, I have pasted below the html template with the modification suggested by you.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> {{ title }} : Graph</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style/main.css') }}">
{% if sending_mail %}
<style>
{{ get_resource_as_string('static\style\main.css') }}
</style>
{% endif %}
</head>
<body>
<form action="/submit">
<p> {{ shiftsum }}</p>
<div align='left'>
<h1>Task</h1>
<table id="customers">
<th>Task Number</th>
<th>Description</th>
<th>State</th>
{% for records in rec %}
<tr>
<td>{{records['number'] }}</td>
<td>{{records['short_description']}}</td>
<td>{{ state[records['state']]}}</td>
</tr>
{% endfor %}
</table>
</div>
</form>
</body>
</html>
Change the definition of send_email() to as given below,
def send_email(shift, rec, STATES):
msg = Message(subject=shift ,recipients=['user#gmail.com'])
msg.html=render_template('index.html', rec=rec, state=STATES)
mail.send(msg)
And in the index.html make sure you enclose the form inside {% if form %} ... {% endif %} where ... indicates your form code.
I hope this helps.
Update (for fixing the missing css styles)
Add the following in your flask script below app = Flask(__name__) or in respective blueprint file,
def get_resource_as_string(name, charset='utf-8'):
with app.open_resource(name) as f:
return f.read().decode(charset)
app.jinja_env.globals['get_resource_as_string'] = get_resource_as_string
Add the following in the index.html
{% if sending_mail %}
<style>
{{ get_resource_as_string('static/css/styles.css') }}
</style>
{% endif %}
Where static/css/styles.css should be replaced with path to your css file. If more than one css file is there, just add {{ get_resource_as_string('static/css/styles.css') }} for each one of them, with their respective path as argument of get_resource_as_string()
Make the following changes in send_email(),
def send_email(shift, rec, STATES):
msg = Message(subject=shift ,recipients=['user#gmail.com'])
msg.html=render_template('index.html', rec=rec, state=STATES, sending_mail=True)
mail.send(msg)
I have added sending_mail=True as argument to the render_template() so whenever sending_mail is set, the render_template will add the content from the css files to the <style>...</style>.
I hope this fixes the missing css styles.
#George thanks for your help, anyways I have found out what was the missing link here,
so the thing is most of the email client doesn't support CSS that are stored locally(this what I found out, could be other things as well), so I used inline CSS and that is working perfectly and now I can see all the formatting that has been done inline in the HTML Template while sending the email.
thanks again for your help.

How to use links to local server as href in Django?

I want to have links that are clickable . That link is a path in a server.
Example:
file:///I:/IT/Install/Winrar/
SO far I have my view code:
def installables_available(request):
install_path = r'I:/IT/Install/'
list_setup = os.listdir(install_path)
full_path = [os.path.join(install_path, item) for item in list_setup]
return render(request, 'generic/installables.html', {'full_path': full_path})
And the html looks like:
<html lang="en">
<head>
<title>All Installables</title>
</head>
<body>
<h1>Below are all setups available</h1>
{% for name in full_path %}
<ul>
<li><a href={{name}}> {{name}}</a></li>
</ul>
{% endfor %}
<hr>
<p>Thanks for visiting my site.</p>
</body>
</html>
I do get the page showing links but , If I click them, they don't do anything. But hovering on them shows the correct path i.e e.g file:///I:/IT/Install/Winrar/.

Django template img src not working

I want to print an image by using a img src tag in a Django template file "base.html":
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title>Foto</title>
</head>
<body>
<h1>My helpful timestamp site</h1>
<img src="google.png" / >
<hr>
<p>Made by ... </p>
</body>
</html>
In views.py I define:
def hello(request):
return render_to_response('base.html')
But the image does not show up in the browser. If I open it as a simple html file, it shows up in the browser.
In recent versions of django
<img src="{% static 'path/to/image.ext' %}"/>
That happens because Django does not know the path to this image.
Make a folder named static/, and then a folder named images/ in your project root(where your settings.py file resides).
my_project/
my_project/
settings.py
static/
images/
google.png
And then change it to:
<img src="{{STATIC_URL}}images/google.png" / >
More here.
You have got to add load static tag in the beginning of your Django template, best luck with below code.
{% load static %}
<img src="{% static 'path/to/image.ext' %}"/>

django export images and text in the html as pdf

I was having trouble exporting images in an html file as pdf, a similar solution exists here.
The html is being rendered properly on the server. I verified it by cross checking it on a url.
but while trying to download/render the pdf **i get a pdf but which is blank, also it says error in the third line of the download function in views.py
Here is what i tried:
html file:
<html>
<head>
<link href="{{ STATIC_URL }}css/certificate.css" rel="stylesheet"
type="text/css" />
</head>
<body>
<div class="certificate_container">
<div class="statictext">
<p>{{ name }}</p>
</div>
</div>
</body>
<html>
css file:
body{margin:0px; padding:0px;}
.certificate_container{ width:792px; height:612px; background:url("../images/certificate.gif") no-repeat;}
.statictext{width:400px; margin:0px auto; padding-top:240px; height:30px; text-align:center; font:bold 14px Arial, Helvetica, sans-serif; color:#333;}
views.py:
#relevant imports
from reportlab.pdfgen import canvas
import xhtml2pdf.pisa as pisa
import cStringIO as StringIO
def download(request):
html = render_to_string("certificate.html", { 'pagesize' : 'A4', }, context_instance=RequestContext(request))
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(), dest=result, link_callback=fetch_resources )
if not pdf.err:
return HttpResponse(result.getvalue(), mimetype='application/pdf')
return HttpResponse('Gremlins ate your pdf! %s' % cgi.escape(html))
def fetch_resources(uri, rel):
path = os.path.join(settings.STATIC_ROOT, uri.replace(settings.STATIC_URL, ""))
return path
def home(request):
return render(request, 'certificate.html', {'name':'user1'} )
The urls have been taken care of properly.
I later found, this could not be achieved using the above tech stack, hence i tried getting a template image and used PIL to modify it based on context. And that worked.