I am trying to create map in Django using folium. There is no error message, but instead of the map it displays the word 'None'.
I have a django web app that reads from a postgressql database and displays the records. That is working. I want to add a map with markers, and the markers will get coordinates from the postgresql data. When I try to create a map using iframe, I get the word 'None'. I have tried just hard coding a starting location to just create the map. I still get the word 'None'.
I also typed the hard coded coordinates into google maps, and made a flask app that creates the map. They show up fine.
views.py:
from django.shortcuts import render
from django.http import HttpResponse
from .models import PhotoInfo
import folium
import pandas
# Create your views here.
def index(request):
VarPhotoInfo = PhotoInfo.objects.order_by('DateTaken')
context = {'PhotoInfo': VarPhotoInfo }
return render(request,'natureapp/index.html',context)
def show_map(request):
#creation of map comes here + business logic
#PhotoInfo1 = PhotoInfo.objects.order_by('DateTaken')
map = folium.Map(location=[33.57137166666667, -117.76325])
map.save("natureapp/map.html")
context = {'my_map': map }
return render(request, 'natureapp/map.html', context)
map.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>NatureMapper</title>
</head>
<h1>Map goes here </h1>
{{ my_map.render }}
</html>
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>NatureMapper</title>
</head>
<h1>Here it is! </h1>
{% if PhotoInfo %}
{% for Photo in PhotoInfo %}
<p>there is info.</p>
<p> {{ Photo.PhotoName }}</p>
<p> {{ Photo.Lat }}</p>
<p> {{ Photo.Long }}</p>
<p> <img src="{{ Photo.PhotoImage.url }}" width = "240" alt=""></p>
{% endfor %}
{% else %}
<p>there is no info.</p>
{% endif %}
<iframe id="encoder_iframe" height=95% width="90%" src="{% url 'show_map' %}">
</iframe>
</html>
There is no error message. Just the word 'None'
Related
I'm starting with Django and I working with HTML and I would like to convert to pdf.
I have this view which I get the data registered in my DB by id:
def contrato(request, id):
return render(request,'contrato\contrato.html', {'asociado': get_queryset(id)})
This renders me the following html, it is something simple:
<!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>CPS</title>
</head>
<body>
<h1>Contrato de Prestación de Servicios</h1>
<div>
<ul>
{% for dato in asociado %}
<li>Función/Título: {{ dato.job_title }}</li>
<li>nombre completo: {{ dato.first_name }} {{ dato.last_name }}</li>
<li>Email: {{ dato.email }}</li>
<li>RFC: {{ dato.rfc }}</li>
<li>CURP: {{ dato.curp }}</li>
<li>Clabe: {{ dato.interbank_key }}</li>
<li>País: {{ dato.country }}</li>
<li>Status: {{ dato.status }}</li>
<li>Creado: {{dato.created}}</li>
{% endfor %}
</ul>
</div>
</body>
</html>
How can I convert this html to pdf with the registered data to download. I have only achieved an empty pdf (without the data) or only with the H1 header.
I will appreciate any help!
You can use wkhtml2pdf, which will need a HTML document and will generate a pdf file,then return to the generated file to the user, something like this
def contrato(request, id):
HTML = render(request,'contrato\contrato.html', {'asociado': get_queryset(id)}).content
f = open("/tmp/report.html","w")
f.write(HTML)
f.close()
import subprocess
subprocess.run("wkhtml2pdf /tmp/report.html /tmp/report.pdf")
return FileStream(open("/tmp/report.pdf","rb"), as_attachment=True)
Doing this without an external library is going to be pretty complicated and involves transpiling the HTML to PDF.
Instead, you'll probably want to use a library like xhtml2pdf.
First pip install xhtml2pdf. Then update your controller function:
from xhtml2pdf import pisa
# ...
def contrato(request, id):
if request.path_info.split('.')[-1] == "pdf"
return render_pdf(request, 'contrato/contrato.html', {'asociado': get_queryset(id)})
return render(request, 'contrato\contrato.html', {'asociado': get_queryset(id)})
def render_pdf(request, template_path, context)
filename = f'{template_path.split('.')[0]}.pdf'
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="{filename}"'
template = get_template(template_path)
html = template.render(context)
pisa_status = pisa.CreatePDF(html, dest=response)
if pisa_status.err:
return HttpResponse(f'We had some errors <pre>{html}</pre>')
return response
For more advanced use cases, you'll probably want to refer to the documentation linked above.
I tried to make a flask app that gets a CSV file from the user, then fits my ML algorithm and finally shows two scatter plots.
Although I could show individual scatter plots via Markup(file_html(plot_obj, CDN, "my plot"), when I use components(plot_obj), and render_template to show both of them together it does not show any of them. Also, I have no error in the console.
I am able to upload the data, then run my algorithm and get the results in the console, however I still don't see the plots.
here is my app.py:
from prad_run import fit
from plots_anomalies import tsne_plot
from bokeh.resources import INLINE, CDN
from bokeh.plotting import figure
import os
from flask import Flask, flash, request, redirect, render_template
from pr_run import fit
from plots import tsne_plot
app = Flask(__name__)
#app.route('/',methods = ['GET'])
def home():
return render_template('home.html')
#app.route('/', methods=['POST'])
def results():
if request.method == 'POST':
file = request.files['file']
df = pd.read_csv(file)
gold_label, df_pr = fit(df)
y_pr = df_pr.loc[:, 'avg_score']
X_tsne = df_pr.drop(columns='avg_score')
tsne_value = plot(X_tsne)
p_true = figure(title="Data with True Labels",plot_width=300, plot_height=300,)
true_df = pd.DataFrame(data=tsne_value, columns=["v1", "v2"])
colormap = {1: 'red', 0: 'green'}
true_df['label'] = gold_label
true_df["color"] = true_df['label'].map(lambda x: colormap[x])
p_true.scatter(true_df['v1'], true_df['v2'], color=true_df['color'], fill_alpha=0.8, size=5)
p_pr = figure(title="Predicted results",plot_width=300, plot_height=300)
tsne_df = pd.DataFrame(data=tsne_value, columns=["v1", "v2"])
tsne_df["pr"] = [1 if x > 0.115 else 0 for x in y_pr]
colormap = {1: 'red', 0: 'green'}
tsne_df['color'] = tsne_df['pr'].map(lambda x: colormap[x])
print(tsne_df['color'].values)
p_pr.scatter(tsne_df['v1'], tsne_df['v2'], color=tsne_df['color'], fill_alpha=0.8, size=7)
js1, divs1 = components(p_true)
js2, divs2 = components(p_pr)
return render_template("home.html", js1=js1, divs1=divs1,js2=js2, divs2=divs2 )
In my home.html:
<!doctype html>
<html>
<title>Python Flask File Upload Example</title>
<h2>Select a file to upload</h2>
<p>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</p>
<form method="post" action="/" enctype="multipart/form-data">
<dl>
<p>
<input type="file" name="file" autocomplete="off" required>
</p>
</dl>
<p>
<input type="submit" value="Submit">
</p>
</form>
<meta charset="UTF-8">
<head>
<title>Figure examples</title>
<link rel="stylesheet" href="http://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.css" type="text/css" />
<script type="text/javascript" src="http://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"></script>
<link
href="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.css"
rel="stylesheet" type="text/css">
<link
href="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.4.0.min.css"
rel="stylesheet" type="text/css">
<link
href="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.4.0.min.css"
rel="stylesheet" type="text/css">
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.4.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.4.0.min.js"></script>
{{ script|safe }}
</head>
<body>
<div style="width: 20%; display: inline-block;">
{{ divs1 | safe }}
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.4.0.min.js"></script>
{{ js1 | safe }}
</div>
<div style="width: 20%; display: inline-block;">
{{ divs2 | safe }}
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.4.0.min.js"></script>
{{ js2 | safe }}
</div>
</body>
</html>
Any idea what is causing this problem?
The <script> tags returned by components have to go in the <head> not <body>. Additionally, you don't need to load BokehJS from CDN multiple times as you are doing above.
You might also want to consider the newer json_items API for embedding, which can be simpler in many cases:
https://docs.bokeh.org/en/latest/docs/user_guide/embed.html?highlight=components#json-items
I found out that the reason that my plots did not display was using Conda environment. If you use Bokeh and Flask I encourage you to use virtualenv in the same folder that you are making your app instead of creating Conda environment.
I am reading gps coordinates from a postgressql database, and I am using folium to create a map. I use iframe to embed the map in index.html. The data is being read and displayed in index.html, but the embedded map.html throws an error saying ''QuerySet' object has no attribute 'Lat'' - but my recordset does have a field called Lat and I use it in index.html
I am displaying the data (latitude, longitude, a picture taken at those coordinates) in index.html. I've created a model and have data in a postgressql database. I created a function in views.py where I'm looping through the dataset to create markers in a folium map. Then I'm using iframe to embed it in an index.html
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import PhotoInfo
import folium
# Create your views here.
def index(request):
VarPhotoInfo = PhotoInfo.objects.order_by('DateTaken')
context = {'PhotoInfo': VarPhotoInfo }
return render(request,'natureapp/index.html',context)
def show_map(request):
#creation of map comes here + business logic
PhotoInfo1 = PhotoInfo.objects.order_by('DateTaken')
m = folium.Map([33.571345, -117.763265], zoom_start=10)
test = folium.Html('<b>Hello world</b>', script=True)
popup = folium.Popup(test, max_width=2650)
folium.RegularPolygonMarker(location=[33.571345, -117.763265], popup=popup).add_to(m)
fg = folium.FeatureGroup(name = "MyMap")
for lt, ln, el, fn in zip(PhotoInfo1.Lat,PhotoInfo1.Lon, PhotoInfo1.DateTaken, PhotoInfo1.PhotoName):
fg.add_child(folium.Marker(location={float(lt),float(ln)},popup = str(el) +' file: '+fn, icon = folium.Icon(color='green')))
m.add_child(fg)
str = m.get_root().render()
context = {'MyMap': str}
return render(request, 'natureapp/map.html', context)
map.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>NatureMapper</title>
</head>
<h1>Map goes here </h1>
{{ my_map }}
</html>
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>NatureMapper</title>
</head>
<h1>Here it is! </h1>
{% if PhotoInfo %}
{% for Photo in PhotoInfo %}
<p>there is info.</p>
<p> {{ Photo.PhotoName }}</p>
<p> {{ Photo.Lat }}</p>
<p> {{ Photo.Long }}</p>
<p> <img src="{{ Photo.PhotoImage.url }}" width = "240" alt=""></p>
{% endfor %}
{% else %}
<p>there is no info.</p>
{% endif %}
<iframe id="encoder_iframe" height=95% width="70%" src="{% url 'show_map' %}">
</iframe>
</html>
Index.html displays all the data including the picture fine.
show_map has the following error message:
AttributeError at /map 'QuerySet' object has no attribute 'Lat'
Request Method: GET Request URL: http://127.0.0.1:8000/map Django
Version: 2.2 Exception Type: AttributeError Exception Value:
'QuerySet' object has no attribute 'Lat' Exception
Location: C:\Users\denjs\Documents\DjangoProjects\NatureMapper2\naturemapper2\natureapp\views.py
in show_map, line 22 Python
Executable: C:\Users\denjs\AppData\Local\conda\conda\envs\mydjangoenv\python.exe
Python Version: 3.7.2 Python Path:
['C:\Users\denjs\Documents\DjangoProjects\NatureMapper2\naturemapper2',
'C:\Users\denjs\AppData\Local\conda\conda\envs\mydjangoenv\python37.zip',
'C:\Users\denjs\AppData\Local\conda\conda\envs\mydjangoenv\DLLs',
'C:\Users\denjs\AppData\Local\conda\conda\envs\mydjangoenv\lib',
'C:\Users\denjs\AppData\Local\conda\conda\envs\mydjangoenv',
'C:\Users\denjs\AppData\Local\conda\conda\envs\mydjangoenv\lib\site-packages',
'C:\Users\denjs\AppData\Local\conda\conda\envs\mydjangoenv\lib\site-packages\win32',
'C:\Users\denjs\AppData\Local\conda\conda\envs\mydjangoenv\lib\site-packages\win32\lib',
'C:\Users\denjs\AppData\Local\conda\conda\envs\mydjangoenv\lib\site-packages\Pythonwin']
Server time: Tue, 16 Jul 2019 01:40:33 +0000
A queryset is a list of objects. The queryset does not have the Lat attribute attached to it.
In the index.html you iterate over a queryset of PhotoInfo objects which do have the Lat attribute.
{% for Photo in PhotoInfo %}
<p> {{ Photo.Lat }}</p>
{% endif %}
Where in the def show_map(request) view you are not iterating over a queryset and instead are trying to access the Lat attribute on a queryset.
PhotoInfo1 = PhotoInfo.objects.order_by('DateTaken')
# PhotoInfo1 is not a single object, but rather a list of objects
Either change the queryset in def show_map(request) to return only a single instance:
PhotoInfo1 = PhotoInfo.objects.get(id=1)
Or iterate over the PhotoInfo1 queryset like you did in the template.
django - I don't see anything from database when i want to display the contents on cards/index page. in the admin section it's working but here not working. BTW sorry my bad communication
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.all_id_cards),
]
views.py
from django.shortcuts import render
from .models import IdCard
def all_id_cards(request):
cards = IdCard.objects.all()
return render(request, 'cards/cards_index.html', { 'cards': cards })
models.py
from django.db import models
# Create your models here.
class IdCard(models.Model):
emp_id = models.CharField(max_length=12)
emp_name = models.CharField(max_length=40)
emp_title = models.CharField(max_length=30)
emp_telephone = models.CharField(max_length=12)
emp_email = models.CharField(max_length=30)
emp_generation = models.CharField(max_length=20)
emp_status = models.CharField(max_length=20)
def __str__(self):
return self.emp_name
cards_index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Homepage</title>
</head>
<body>
<h1>Identity Cards</h1>
<div class="identitycards">
{% for cards in cards %}
<div class="identitycard">
<p>{{ IdCard.emp_name }}</p>
</div>
{% endfor %}
</div>
</body>
</html>
There are two problems here:
you iterate over the items with {% for cards in cards %}, so the iterator has the same name as the collection. Although it might work, it is better to avoid that, since it can result in unpredictable behavior; and
you render the content with {{ IdCard.emp_name }}. IdCard is not passed to the rendering, but anyway, you need to use card, so {{ card.emp_name }}.
If we fix the two issues we get as template file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Homepage</title>
</head>
<body>
<h1>Identity Cards</h1>
<div class="identitycards">
{% for card in cards %}
<div class="identitycard">
<p>{{ card.emp_name }}</p>
</div>
{% endfor %}
</div>
</body>
</html>
I tried to link an anchor to another page in Django. But I get the error " Reverse for 'animals.all_animals' not found. 'animals.all_animals' is not a valid view function or pattern name."
I tried several ways to do it.. no success. I have one app called animals and Im tyring to display the list of animals in the by clicking an anchor on the homepage. I attached here my Django files.
from django.shortcuts import render, get_object_or_404
from .models import Animal
def animal_list(request):
animals = Animal.objects.all()
return render(request, 'animals/animal_list.html', {'animals': animals})
// and here is the html
{% for animal in animals %}
<h1>{{animal.species}}</h1>
<p>{{animal.description}}</p>
{% endfor %}
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.animal_list, name='all_animals'),
url(r'^(?P<pk>\d+)/$', views.animal_detail, name='all_details'),
]
{% load static from staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Animals Site</title>
<link href="{% static 'css/base.css'%}" rel="stylesheet">
</head>
<body>
{% block content %}
<nav>
Animal List
</nav>
<a></a><h2>I love cats!</h2>
{% endblock content %}
{% block listbar %}
<ul>
<li>Sphynx</li>
<li>Catto</li>
<li>Bengal</li>
</ul>
{% endblock listbar %}
</body>
</html>
{% block listcolor%}
<style>
h2{
font-family: 'Calibri';
color: blue;
}
</style>
{% endblock listcolor%
You need a colon not a dot in the notation:
Animal List
Or in case the included urls from your app are not namespaced:
Animal List