AttributeError at /map creating folium map in Django - python

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.

Related

How to convert html to pdf in Django?

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.

Nonetype error while saving file with dropzone js in Django

I am trying to save documents/images into my SQL database using dropzone.js ,for my web app made using Django
HTML FILE:
{% extends 'Main/logged_base_expert.html' %}
{% block content %}
{% load static %}
<head>
<script src="https://rawgit.com/enyo/dropzone/master/dist/dropzone.js"></script>
<link rel="stylesheet" href="https://rawgit.com/enyo/dropzone/master/dist/dropzone.css">
</head>
<body>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.7.5/css/bootstrap-select.min.css" media="screen">
<form action="{% url 'document_upload' %}" method = "POST" class="dropzone dz" role="form" enctype="multipart/form-data">
{% csrf_token %}
<div class="fallback">
<input name="file" type="file" id="file" multiple >
</div>
<button type="submit" class="form-control" id="cf-submit" name="submit">Submit</button>
</form>
<!-- client section end -->
<!-- footer section start -->
{% endblock %}
views.py :
def document_upload(request):
c = main.objects.get(username = request.session['username'])
unq_id = c.unq_id
print("overall")
if request.method == 'POST':
images = request.FILES.get('file')
print("image")
fs = FileSystemStorage()
filename = fs.save(images.name, images)
Doc1 = Doc(user_id = unq_id, upload = images)
Doc1.save()
return render(request, 'Main/document_upload.html')
models.py:
class Doc(models.Model):
unq_id = models.AutoField(primary_key=True)
user_id = models.BigIntegerField()
upload = models.ImageField(upload_to= 'expert/images')
def __str__(self):
return str(self.unq_id)
The issue I keep facing is that , i keep getting the error
AttributeError at /document_upload/
'NoneType' object has no attribute 'name'
It occurs in the following line, in views.py:
filename = fs.save(images.name, images)
Additional Info : the relative path of the image seems to be storing just perfectly in the database, but since i keep getting the error , i am unable to redirect the app to another page
you're getting AttributeError because this couldn't be found in your request - request.FILES.get('file'). Print request.FILES and see what you have in there.

Folium map in Django only says 'None'

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'

django - I don't see anything from database when i want to display the contents on cards/index page

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>

Form input-box not displaying

I'm trying to display a simple form input-text box with Django. I'm am deploying on Amazon AWS. The site works fine on a different server (pythonanywhere) but there is a major problem on AWS. Specifically, the input box is not being displayed. I'm using templates as follows:
home.html
{% extends 'lists/base.html' %}
{% block header_text %}Start a new To-Do list {% endblock %}
{% block form_action %}{% url 'new_list' %}{% endblock %}
base.html
<!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">
<title>To-Do lists</title>
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/base.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3 jumbotron">
<div class="text-center">
<h1>{% block header_text %}{% endblock %}</h1>
<form method="POST" action="{% block form_action %}{% endblock %}">
{{ form.text }}
{% csrf_token %}
{% if form.errors %}
<div class = "form-group has-error">
<span class = "help-block">{{ form.text.errors }}</span>
</div>
{% endif %}
</form>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-3">
{% block table %}
{% endblock %}
</div>
</div>
</div>
</body>
</html>
models.py
from django.db import models
from django
.core.urlresolvers import reverse
class List(models.Model):
def get_absolute_url(self):
return reverse('view_list', args=[self.id])
# Create your models here.
class Item(models.Model):
text = models.TextField(default = '')
list = models.ForeignKey(List, default = None)
#list = models.ForeignKey(List , default=None)
forms.py
from django import forms
from lists.models import Item
EMPTY_ITEM_ERROR = "You can't have an empty list item"
class ItemForm(forms.models.ModelForm):
class Meta:
model = Item
fields = ('text',)
widgets ={
'text' : forms.fields.TextInput(attrs={
'placeholder': 'Enter a to-do item',
'class': 'form-control input-lg',
}),
}
error_messages = {
'text' : { 'required': EMPTY_ITEM_ERROR }
}
views.py
from django.shortcuts import redirect, render
from lists.models import Item, List
from django.core.exceptions import ValidationError
from lists.forms import ItemForm
from lists.models import Item, List
# Create your views here.
def home_page(request):
return render(request, 'lists/home.html', {'form': ItemForm()})
urls.py
from django.conf.urls import url
from lists import views
urlpatterns = [
url(r'^new$', views.new_list, name='new_list'),
url(r'^(\d+)/$', views.view_list, name='view_list'),
]
Currently the site displays the following:
However it should (and does on a different website) display this:
I've pushed/pulled the entire project to github and the code between each site is identical, yet I'm not seeing why the text input isn't displayed, unless the form needs to be initialized in Django somehow or a quirk to AWS?
When comparing the two sites, the one without the text-box does not generate the following:
<input class="form-control input-lg" id="id_text" name="text" placeholder="Enter a to-do item" type="text" />
Even though it should, per the base.html syntax.
Updated
The full views.py (per suggested comment) is:
from django.shortcuts import redirect, render
from lists.models import Item, List
from django.core.exceptions import ValidationError
from lists.forms import ItemForm
from lists.models import Item, List
# Create your views here.
def home_page(request):
return render(request, 'lists/home.html', {'form': ItemForm()})
def new_list(request):
form = ItemForm(data=request.POST)
if form.is_valid():
list_ = List.objects.create()
Item.objects.create(text=request.POST['text'], list=list_)
return redirect(list_)
else:
return render(request, 'lists/home.html', {"form": form})
def view_list(request, list_id):
list_ = List.objects.get(id=list_id)
form = ItemForm()
if request.method == 'POST':
form = ItemForm(data=request.POST)
if form.is_valid():
Item.objects.create(text=request.POST['text'], list=list_)
return redirect(list_)
return render(request, 'lists/list.html', {'list': list_, "form": form})
In my experience with Django, there are 2 things you often (always?) need to do to get static files to "refresh" after pushing them to a remote server:
Run ./manage.py collectstatic to make sure all your static files are in the right place.
While sshed into your server run the command sudo reboot now to restart your server (note that this will kick you out of your ssh session, and your server will be unreachable for a moment - usually just a few seconds in my case).
As for step 2 there might be a better way to do this, but in my experience, when I update static files the updated version is not served until I do this, and restarting nginx or the like is not sufficient for the changes to take effect. Note that this will mean that your site, if live, will not be reachable for a few seconds while the server is restarting (which is what makes me think there might be a better way to do it) but for me and my small user base this is not a big issue.
From reading some other posts about static files not updating, it seems like it could also be the case that your browser is caching the static files, and that restarting your browser/clearing the cache might do the trick as well, but I have not had a chance to try this yet.

Categories

Resources