TemplateDoesNotExist at / (home.html) - django

I'm working on an example Placeholder Image Server. This uses a single file approach, so urls, views, settings, are all in just one file called placeholder.py.
Each time I try visiting http://localhost:8000 (the homepage), I get TemplateDoesNotExist at / thrown at me. I can't figure out what's wrong. Below is the project structure:
/placeholder
placeholder.py
/templates
home.html
/static
style.css
Here's the content of each file:
placeholder.py
import hashlib
import os
import sys
from io import BytesIO
from PIL import Image, ImageDraw
from django.conf import settings
from django import forms
from django.urls import path, reverse
from django.core.cache import cache
from django.core.wsgi import get_wsgi_application
from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import render
from django.views.decorators.http import etag
from django.core.management import execute_from_command_line
# settings likely to change between environments
DEBUG = os.environ.get('DEBUG', 'on') == 'on'
SECRET_KEY = os.environ.get('SECRET_KEY', 'soj-4^4nho$ifsxsoi1+a8&6o&dya)tcivwcg9g_82&8sg*q^9')
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost').split(',')
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# settings
settings.configure(
DEBUG=DEBUG,
SECRET_KEY=SECRET_KEY,
ALLOWED_HOSTS=ALLOWED_HOSTS,
ROOT_URLCONF=__name__,
MIDDLEWARE_CLASSES=(
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
),
INSTALLED_APPS=(
'django.contrib.staticfiles',
),
TEMPLATES=[
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': os.path.join(BASE_DIR, 'templates'),
}
],
STATICFILES_DIRS=(
os.path.join(BASE_DIR, 'static'),
),
STATIC_URL='/static/',
)
# simple form to validate the height and width of an image
class ImageForm(forms.Form):
'''form to validate requested placeholder image'''
width = forms.IntegerField(min_value=1, max_value=2000)
height = forms.IntegerField(min_value=1, max_value=2000)
def generate(self, image_format='PNG'):
'''generate an image of the given type and return as raw bytes'''
width = self.cleaned_data['width']
height = self.cleaned_data['height']
key = '{}.{}.{}'.format(width, height, image_format)
content = cache.get(key)
if content is None:
image = Image.new('RGB', (width, height))
draw = ImageDraw.Draw(image)
text = '{} x {}'.format(width, height)
textwidth, textheight = draw.textsize(text)
if textwidth < width and textheight < height:
texttop = (height - textheight) // 2
textleft = (width - textwidth) // 2
draw.text((textleft, texttop), text, fill=(255, 255, 255))
content = BytesIO()
image.save(content, image_format)
content.seek(0)
cache.set(key, content, 60 * 60)
return content
# for client-side caching
def generate_etag(request, width, height):
content = 'Placeholder: {0} x {1}'.format(width, height)
return hashlib.sha1(content.encode('utf-8')).hexdigest()
# views
def index(request):
example = reverse('placeholder', kwargs={'width':50, 'height':50})
context = {
'example' : request.build_absolute_uri(example)
}
return render(request, 'home.html', context)
#etag(generate_etag) # decorator for client-side caching
def placeholder(request, width, height):
form = ImageForm({'width':width, 'height':height})
if form.is_valid():
image = form.generate()
return HttpResponse(image, content_type='image/png')
else:
return HttpResponseBadRequest('<h1>Invalid Image Request!</h1>')
# the url
urlpatterns = [
path('', index, name='homepage'),
path('image/<int:width>x<int:height>', placeholder, name='placeholder'),
]
# wsgi application
application = get_wsgi_application()
# relevant part from manage.py
if __name__ == "__main__":
execute_from_command_line(sys.argv)
home.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Demo Placeholder Images</title>
<link type="text/css" rel="stylesheet" href="{% static 'style.css' %}">
</head>
<body>
<h1>Demo Placeholder Images</h1>
<p>This server can be used for serving placeholder images for any webpage.</p>
<p>To request a placeholder image of a given width and height simply include
an image with the source pointing to <b>/placeholder/<width>x
<height>/</b> on this server such as:
</p>
<pre><img src="{{ example }}"></pre>
<h2>Examples</h2>
<ul>
<li><img src="{% url 'placeholder' width=50 height=50 %}"></li>
<li><img src="{% url 'placeholder' width=100 height=50 %}"></li>
<li><img src="{% url 'placeholder' width=50 height=100 %}"></li>
</ul>
</body>
</html>
What's wrong?

I think the problem is that your BASE_DIR is incorrect. Because you have one simple flat file, and templates and static files are in subdirectories at the same level, you only need to go to the current directory, not the parent. So it should be:
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

I figured it out. The value of 'DIRS' in the TEMPLATES setting is meant to be a list. Here's what I mean:
...
TEMPLATES=[
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
}
],
...

Related

How to generate link for file download?

I created a model without using FileField() and saved the url into path field. Now while displaying I can see the attributes but I cannot download the file. href treats it as a page and i get an error saying GET request failed.
I need to do the same for static files also.
models.py looks like this:
import os
from django.conf import settings
from django.db import models
# Create your models here.
class Document(models.Model):
code = models.CharField(max_length = 50)
path = models.CharField(max_length = 500)
date_of_submission = models.CharField(max_length = 50)
type = models.CharField(max_length = 50)
title = models.CharField(max_length = 200)
department = models.CharField(max_length = 50)
subject = models.CharField(max_length = 100)
updation_allowed = models.CharField(max_length = 1, default = '0')
#property
def relative_path(self):
return os.path.relpath(self.path, settings.MEDIA_ROOT)
template has some code like this:
<a href = '{{ MEDIA_URL }}{{ value.thesis.relative_path }}'> Thesis </a>
*static files*
<a href='/uploads/report.pdf'> Front Page</a>
I tried using the property and provinding the path myself.
urls.py (project/urls.py)
from django.conf.urls.static import static
urlpatterns = [
...
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
...
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
To allow file downloading you need to create a separate view with FileResponse as a response. This view will take some unique argument (I suppose it will be relative path to the file) with url provided in html template. Inside this view, FileResponse will open your file by provided path and then will return response with your file. I think you should do it like this:
Views.py:
def download_file(request, relative_path): # this is a view with file response
media_root = settings.MEDIA_ROOT
return FileResponse(open(f"{media_root}\{relative_path}", "rb"), as_attachment=True, filename="some_name.smth")
template:
<a href = '{% url "download" relative_path=value.thesis.relative_path %}'> Thesis </a>
*static files*
<a href='/uploads/report.pdf'> Front Page</a>
urls.py:
urlpatterns = [
path("download-file/<slug:relative_path>/", views.download_file, name="download")]
You will need to combine with PATHes to get it to work.

Need help to render img in pdf from template using xhtml2pdf

I'm building a project were i need to get my data into pdf from a template (html), my problem is that the image is not apearing on pdf view.
This is my code:
class GeneratePdf_month(TemplateView):
template_name = "polls/info_month.html"
def get(self, request, *args, **kwargs):
## do some....
data = {
'cliente': cliente,
}
pdf = render_to_pdf(self.template_name, data)
return HttpResponse(pdf, content_type='application/pdf')
## and this is my html template
<head>
{% load staticfiles %}
<title>Detail</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
padding: 10px;
}
</style>
</head>
<body>
<header>BlaBla<img src="{% static 'polls/images/image.png'%}"></header>
</body
Can someone help me?
If your are using xhtmltopdf you also need to provide a link_callback for being abble to display images:
def link_callback(uri, rel):
"""
Convert HTML URIs to absolute system paths so xhtml2pdf can access those
resources
"""
# use short variable names
sUrl = settings.STATIC_URL # Typically /static/
#static Root
sRoot = settings.STATIC_ROOT # Typically /home/userX/project_static/
mUrl = settings.MEDIA_URL # Typically /static/media/
mRoot = settings.MEDIA_ROOT # Typically /home/userX/project_static/media/
# convert URIs to absolute system paths
if uri.startswith(mUrl):
path = os.path.join(mRoot, uri.replace(mUrl, ""))
elif uri.startswith(sUrl):
path = os.path.join(sRoot, uri.replace(sUrl, ""))
else:
return uri # handle absolute uri (ie: http://some.tld/foo.png)
# make sure that file exists
if not os.path.isfile(path):
raise Exception(
'media URI must start with %s or %s' % (sUrl, mUrl)
)
return path
AND don't forget to add the link callback in your render_to_pdf:
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result, link_callback=link_callback)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
You also need to specify the height and widht inside the img tag like:
<img src="{% static 'polls/images/image.png'%}" alt="image" width="200" height="150" />
In settings.py don't forget to define your STATIC_URL AND STATIC_ROOT, MEDIA_URL AND MEDIA_ROOT
Like this for exemple:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'project_name/static/')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'project_name/media/')
Then don't forget to run python manage.py collectstatic in the terminal
More info here: https://xhtml2pdf.readthedocs.io/en/latest/usage.html#using-xhtml2pdf-in-django
in views.py
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
path = os.path.join( BASE_DIR , 'static')
# send 'path' first in context
context = {'path':path , 'any':any }
in template
<img src="{{path}}\img\pic.png" >

Django - Images won´t be displayed in template, but image url showes up. Urls.py Issue?

Using Django 2.1.5 + Bootstrap 4.2 and some Icons from fontawesome
Hello ,
after a long search I decided to post, because most answer are related to older Django versions.
I am relatively new to Django and I like to test all the Function/Class Views and Modelfields. Now I wanted to test how I can display images linked with my database in my template. But unfortunately, images want not display, all I see is image placeholder icon.
I created an app and 2 simple models, with musicians (with images) and cars. The upload via admin works and the blank url are accessible in the Template via {{ modelone.person_pic }}
PROBLEMS SOLVED - See down Below
aquaman / models.py
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
person_pic = models.ImageField(upload_to='artist/', max_length=255, null=True, blank=True )
def __str__(self):
return "{} - {}".format(self.first_name[:25], self.last_name[:25])
class Data_Sheet(models.Model):
car = models.CharField(max_length=30)
color = models.CharField(max_length=30)
def __str__(self):
return "{} - {}".format(self.car[:25], self.color[:25])
views.py
from django.shortcuts import get_object_or_404, render, redirect
from django.utils import timezone
from django.views.generic.list import ListView
from django.views.generic import TemplateView
from .models import Person, Data_Sheet
<…some other views…>
class ArtistView4(TemplateView):
template_name = 'aquaman/artistview4.html'
def get_context_data(self, **kwargs):
context = super(ArtistView4, self).get_context_data(**kwargs)
context['modelone'] = Person.objects.all()
context['modeltwo'] = Data_Sheet.objects.all()
return context
artistview4.html
{% extends 'base.html' %}
{% load static %}
{% block custom_css %}
<link rel="stylesheet" type="text/css" href="{% static 'css/clear_styles.css' %}">
{% endblock %}
{% block content %}
{% for visual in modelone %}
<div align="center">
<h4 class="">{{ visual.first_name }}</h4>
<h4 class="">{{ visual.last_name }}</h4>
<h4 class="">{{ visual.person_pic }}</h4> <!-- to check if url is displayed -->
</div>
<img src="{{ visual.person_pic.url }}">
</div>
{% endfor %}
{% endblock %}
urls.py
from django.urls import path
from . import views
from .views import AquaListView, AquaListView2, AquaListView3, ArtistView4
app_name='aquaman'
urlpatterns = [
path('home/', views.aqua_home, name='aqua_home'),
path('aqua_listview/', AquaListView.as_view(), name='aqua_listview'),
path('aqua_listview2/', AquaListView2.as_view(), name='aqua_listview2'),
path('aqua_listview3/', AquaListView3.as_view(), name='aqua_listview3'),
path('arstistview4/', ArtistView4.as_view(), name='artistview4'),
]
my approach
As far as I understand the documentation. I have to add this lines to the urls.py in the urlpattern, so that everything gets directed.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
So my urls.py looks like this now
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from . import views
from .views import AquaListView, AquaListView2, AquaListView3, ArtistView4
app_name='aquaman'
urlpatterns = [
path('home/', views.aqua_home, name='aqua_home'),
path('aqua_listview/', AquaListView.as_view(), name='aqua_listview'),
path('aqua_listview2/', AquaListView2.as_view(), name='aqua_listview2'),
path('aqua_listview3/', AquaListView3.as_view(), name='aqua_listview3'),
path('arstistview4/', ArtistView4.as_view(), name='artistview4'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
This is what i added in my settings.py
TEMPLATES = [
{
<…>
'django.template.context_processors.media',
<…>
},
]
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
'/var/www/static/',
]
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
So far nothing changed. Django shows me the last name correctly in the template, but I only see image place holders and no images.
Django Server
Not Found: /media/artist/freddy_mercury.jpg
Not Found: /media/artist/kurt_cobain.jpg
Not Found: /media/artist/ella_fitzgerald.PNG
Not Found: /media/artist/amy_winehouse.PNG
[07/Feb/2019 18:42:49] "GET /media/artist/ella_fitzgerald.PNG HTTP/1.1" 404 2257
When i upload a image via admin from my desktop Django automatically saves the pictures in **MyProject/media/artist>** but at the same time django can not find these images?
If go directly to the images via http://127.0.0.1:8000/media/artist/kurt_cobain.jpg for example, django shows me this:
The current path, media/artist/kurt_cobain.jpg, didn't match any of these.
Even though Django puts the picture via upload in the BaseDir/media/artist folder.
Maybe I missed the "Serving files in development" aka if settings.DEBUG:
https://docs.djangoproject.com/en/2.1/ref/views/
But when I add this also nothing happens.
I really like to thank everyone, who might have a hint
Problem Solved
Alright, I misunderstand something in the Docs maybe it´s not so obvious.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [...] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
This has to be added in the "MainApp/urls.py" not in your "MyOtherApps/urls.py". I thought just because I only need Images in a specific app I have to add these lines in these specific App urls.py.
Rock On & Peace

problems in constructing webmap using django leaflet with the data in database

I have done my leaflet program using django-leaflet but the map is not displaying anything in output
Here is the code
models.py
from django.db import models
from django.contrib.gis.db import models as gismodels
class MushroomSpot(gismodels.Model):
title = models.CharField(max_length=256)
id1=models.IntegerField(primary_key=True)
geom = gismodels.PointField()
objects = gismodels.GeoManager()
def __unicode__(self):
return self.title
urls.py
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from django.contrib import admin
from django.views.generic import TemplateView
from djgeojson.views import GeoJSONLayerView
from .models import MushroomSpot
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='index.html'), name='home'),
url(r'^data.geojson$', GeoJSONLayerView.as_view(model=MushroomSpot), name='data'),
]
index.html
{% load leaflet_tags %}
<html>
<head>
{% leaflet_js %}
{% leaflet_css %}
</head>
<body>
<h1>Weather Stations</h1>
{% leaflet_map "main" callback="main_map_init" %}
<script type="text/javascript">
function main_map_init (map, options) {
var dataurl = '{% url "data" %}';
// Download GeoJSON via Ajax
$.getJSON(dataurl, function (data) {
// Add GeoJSON layer
L.geoJson(data).addTo(map);
});
}
</script>
</body>
</html>
contents related to leaflet in settings.py
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.spatialite',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
SPATIALITE_LIBRARY_PATH = 'mod_spatialite'
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR
LEAFLET_CONFIG = {
'DEFAULT_ZOOM': 6,
'MIN_ZOOM': 1,
'MAX_ZOOM': 20,
}
And I run the setup.py file which has
import csv
from django.contrib.gis.geos import Point
from mushrooms.models import MushroomSpot
csv_file = 'mycsv.csv'
def dms2dec(value):
"""
Degres Minutes Seconds to Decimal degres
"""
degres, minutes, seconds = value.split()
#seconds, direction = seconds[:-1], seconds[-1]
dec = float(degres) + float(minutes)/60 + float(seconds)/3600
#if direction in ('S', 'W'):
# return -dec
return dec
reader = csv.DictReader(open(csv_file), delimiter=",")
for line in reader:
lng = dms2dec(line.pop('mlong'))
lat = dms2dec(line.pop('mlat'))
wmoid = int(line.pop('id'))
name = line.pop('place').title()
print(lng,lat)
MushroomSpot(id1=wmoid, title=name, geom=Point(lng, lat)).save()
Please help me in getting the output map in screen
I dont know what is the error in it
The csv file contains the data of about 8 cities in india
And I want the desired India map as an interactive webmap
Please let me to my desired output

Can't get images to work in django

I'm getting a 404 error when trying to serve user uploaded files in local. I've tried a lot of suggestions from the forums but I can't get it to work.
This is the error I can see on the logs. The images get uploaded properly to media/images but when I try to use that same image I get a 404 not found. I've tried to put the absolute path and didn't work either. Could anybody please help me? Thanks
[03/Feb/2018 23:32:00] "GET /idealistos/30/ HTTP/1.1" 200 483
Not Found: /media/images/_D3L8637.jpg
[03/Feb/2018 23:32:01] "GET /media/images/_D3L8637.jpg HTTP/1.1" 404 2239
settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'static')
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
# Media files
MEDIA_ROOT = 'media/'
MEDIA_URL = '/media/'
models.py
from django.db import models
from django.forms import ModelForm
from django.utils import timezone
from django.contrib.admin.widgets import AdminDateWidget
# Create your models here.
class Anuncio(models.Model):
title = models.CharField(max_length=40)
description = models.CharField(max_length=300)
price = models.CharField(max_length=10)
city = models.CharField(max_length=20)
state = models.CharField(max_length=20)
country = models.CharField(max_length=20)
postcode = models.CharField(max_length=20)
foto = models.FileField(null=True, blank=True, upload_to='images/')
pub_date = models.DateTimeField(default=timezone.datetime.now())
def __str__(self):
return self.title
def __unicode__(self):
return price
class AnuncioForm(ModelForm):
class Meta:
model = Anuncio
fields = ['title', 'description', 'price', 'city', 'state', 'country','postcode','foto']
views.py
from django.http import Http404, HttpResponseRedirect
from django.views.generic import ListView
from django import forms
from django.utils import timezone
#from django.template import loader
from django.shortcuts import render, get_object_or_404, redirect
from .models import Anuncio, AnuncioForm
#Creates a list from a model. Used for the ad index view.
class AnuncioList(ListView):
model = Anuncio
#Creates a detail view of the Ad
def detail(request, anuncio_id):
try:
anuncio_detalle = get_object_or_404(Anuncio, pk=anuncio_id)
#anuncio_detalle = Anuncio.objects.get(pk=anuncio_id)
except Anuncio.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'idealistos/detail.html', {'anuncio_detalle':anuncio_detalle})
def add_form(request):
if request.method == 'POST':
form = AnuncioForm(request.POST,request.FILES)
if form.is_valid():
new_add = form.save()
new_add.pub_date = timezone.now()
return redirect ('idealistos:index')
else:
form = AnuncioForm()
return render(request, 'idealistos/create_add.html', {'form':form,})
url.py
from django.conf.urls.static import static
from django.conf import settings
from django.urls import path
from . import views
from idealistos.views import AnuncioList
app_name ='idealistos'
urlpatterns = [
# ex: /idealistos/
path('', AnuncioList.as_view(), name='index'),
# ex: /idealistos/5/
path('<int:anuncio_id>/', views.detail, name='detail'),
#ex: /idealistos/add_form
path('add_form/', views.add_form, name='add_form'),
]
urlpatterns+=static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
Template
<head>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
</head>
<body>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'idealistos/idealistos.css' %}" />
<h1>{{ anuncio_detalle }}</h1>
<ul>
<li>{{ anuncio_detalle.description }}</li>
<li>{{ anuncio_detalle.city }}, {{ anuncio_detalle.country }} CP:{{ anuncio_detalle.postcode }}</li>
<li>{{ anuncio_detalle.pub_date }}</li>
<img src={{anuncio_detalle.foto.url}}>
</ul>
</body>
Just try giving MEDIA_ROOT and serving in urls.py when DEBUG=True.
models.py
foto = models.ImageField(upload_to='images/', null=True, blank=True)
settings.py
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'media')
MEDIA_URL = '/media/'
urls.py
from django.conf.urls import url, include
from django.contrib import admin
from django.views.static import serve
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
#Other Urls
. . . . .
. . . . .
# admin
url(r'^admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if settings.DEBUG:
urlpatterns += [
url(r'^media/(?P<path>.*)$', serve, {
'document_root': settings.MEDIA_ROOT
}),
]
I hope that you are seeing the uploaded file correctly.
For local development, try adding the following in your base urls.py
if settings.DEBUG is True:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)