Build HTML from Django View - python

I need to construct the HTML body from a Django view and I cannot find a solution to refer correctly a JPG file ( must say that the HTML is much larger then this, but with other stuff seems that is working for me
):
I've tried this:
from django.template import Template
...
html = Template('<IMG SRC="{% static "base/images/course/website-46-2.jpg" %}">')
return HttpResponse( html )
And I get this error:
Invalid block tag on line 1: 'static'. Did you forget to register or load this tag?
In Django template I resolve this by loading the static files:
{% load static %}
How can I do this in Python ( Django View ) ? Or any other suggestion is much appreciated.
I've tried different solution that I have found on this site and others but none seems to work for me.
Django Version: 2.2.1

You can create an engine with the static library as a built-in. This makes it available to the template without calling {% load static %} first.
from django.template import Template, Context, Engine
engine = Engine(builtins=['django.templatetags.static'])
template = engine.from_string('<IMG SRC="{% static "base/images/course/website-46-2.jpg" %}">')
return HttpResponse(template.render(Context()))

Have you set your STATIC_URL in settings.py? You can do this by the following:
STATIC_URL = '/static/'
Your image would then be found under 'your_app/static/base/images/course/website-46-2.jpg'.
Does the folder structure follow this convention? If not you can set the STATIC_URL to '/base/'

def startchat(request):
template=loader.get_template('app1/chatbot.html')
return HttpResponse(template.render())
This function loads the html page into Django.
Before that , we need to import the module
from django.template import loader

Related

Can't get Dynamic image URL work in Django

I'm trying to show an img with the Django dynamic url, but I cant get the dynamic url right
url.py
path('Obra/<int:id>/', views.detalle_obra, name="detalle_obra"),
work-single.html
...<img src="{{object.img.url}}"
views.py
def works(request, id):
obj = Work.objects.get(id=id)
context= {
'object':obj
}
return render(request, 'works-single.html',context)
when I render the template this image pop on the console:
Not Found: /Obra/1/static/mySiteWork/img/uploads/Proyecto Obra Cerrillos/P5230031.jpg
I don't know why is showing the "/Obra/1/". When I print {{object.img.url}} it will only show me the "static path static/mySiteWork/img/uploads/Proyecto Obra Cerrillos/P5230031.jpg"
the static files works fine in the rest of templates
Thanks in advance.
This is most likely because of the value of the MEDIA_URL variable from the settings file. The argument upload_to from the forms is relative to the MEDIA_ROOT/MEDIA_URL. Django calculates the path to a user uploaded file as MEDIA_ROOT/MEDIA_URL/file_url.
Seems that MEDIA_URL in your settings is set to "Obra/1".
I solved the problem:
I change this on the html template:
<img src="{{object.img.url}}">
for this:
<img src="/{{object.img.url}}">
Not sure why... but it works fine

Django 1.11 404 Page while Debug=True

Without making things difficult, I just want to show a special 404 render with staticfiles.
If you set DEBUG = False you can use in urls.py
handler404 = 'app.views.handler404'
But it is without staticfiles. I don't want to install a web server for a simple app.
With DEBUG = True in urls
url(r'^404/$', views.handler400)
is not overriding the default Page not found (404) page.
What is the easy way to achieve a render e.g. when you type localhost/asdfhjfsda with staticfiles when DEBUG=True?
Thanks in advance...
Easiest way to do this post Django 1.9 is in your urls.py:
from django.views.defaults import page_not_found
url(r'^404/$', page_not_found, {'exception': Exception()})
It wants an exception, give it an exception :)
In django 1.10 docs:
Changed in Django 1.9:
The signature of page_not_found() changed. The function now accepts a second parameter, the exception that triggered the error. A useful representation of the exception is also passed in the template context.
Have a look at your 'app.views.handler404' definition, it might miss a parameter, and maybe it's that why the r'^404/$'handler doesn't provide you with the correct method invocation.
I have a complete solution
My development environment:
Windows 7, Python 3.5.2, Django 1.11, WAMP 3.0.6 (Apache 2.4.23, mod_wsgi)
Suppose you have error_404.html template with static files
Create next directory structure ("mysite" - Django project root folder)
mysite\
mysite\
settings.py
urls.py
views.py
static\
error404\
files\
style.css
image.jpg
templates\
error404\
error_404.html
mysite\mysite\settings.py
import os
DEBUG = False
TEMPLATES = [{
..
'DIRS': [os.path.join(BASE_DIR, 'templates')],
..
}]
STATIC_URL = '/static/'
STATIC_ROOT = 'FullPathToYourSite.com/mysite/static/'
mysite\mysite\urls.py
from django.conf.urls import handler404, handler500
from . import views
urlpatterns = [..]
handler404 = views.error_404
handler500 = views.error_404
mysite\mysite\views.py
from django.shortcuts import render
def error_404(request):
return render(request, 'error404/error_404.html')
Some Jinjo logic in "error_404.html" (pseudocode)
{% load staticfiles %}
...
link type="text/css" href="{% static 'error404/files/style.css' %}"
...
img src="{% static 'error404/files/image.jpg' %}"
...

Incorporating existing html pages into Django

I have several hundred static html pages, with an index html page, that I need to bring into Django. I can't figure out the easiest way to do that, I know I'm missing something simple. Any advice?
Nothing fancy needed, just need to dump them in a directory and allow users to navigate to them.
You need to create a view and a url for each html template, iI'm going to put you a simple example here but it's highly recommended that you read Django's documentation or a tutorial :
First, you create a view in a views.py file :
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.views.generic import View
class LoadTemplateView(View):
template_name = ['thenameofyourdjangoapp/yourtemplatename.html']
#You put any code you may need here
def get(self, request, *args, **kwargs):
return render(request, self.template_name)
Then, you must create a url that reads that view in a urls.py file :
from django.conf.urls import patterns, url
#Here you import from views the view you created
from .views import LoadTemplateView
urlpatterns = patterns(
url(r'^myurl/$', LoadTemplateView.as_view(), name="load_template"),
)
Last, in your let's say home html template, you assign this url to a submit button in order to call it by the name you gave it on urls.py (load_template in this case) :
<html>
<body>
<div>
<a class="option-admin" id="id_go" href ="{% url 'yourdjangoappname:load_template' %}"> Go to template </a>
</body>
</html>
</div>
As I said anyway, it's better that you read the complete Django documentation as well:
https://docs.djangoproject.com/en/1.9/
If these are legacy static pages that you do not plan to touch again, then I'd leave django out of it. I'd put them all in a directory or subdomain and serve them directly from the server (probably nginx, maybe apache, whatever you're using). As a general rule, you don't want Django serving static assets, you want the proxy server serving them.
You COULD move them into Django and manage them like other Django static assets, as described in the Managing Static Files Documentation, but if they're already out there, then there's not a whole lot of advantage over just serving them as outlined above.
And finally, if you wish to fully integrate them into your Django site, then you should probably start with the template documentation.

Django Static URL not rendering images correctly

I'm writing a view that displays a set of images on a page.
This is the model
#models.py
class Movie(models.Model):
title = models.CharField(max_length = 500)
poster = models.ImageField(upload_to = 'qanda/static/movie_posters')
#index.html
<img src = "{{ STATIC_URL }}movie_posters/{{ movie.poster }}"></a>
When I runserver, the image doesn't appear. The URL the image is trying to load is
http://127.0.0.1:8000/static/movie_posters/qanda/static/movie_posters/image.jpg
When the URL it should be trying to load is
http://127.0.0.1:8000/static/movie_posters/image.jpg
My assumption is that since movie.poster is located at 'qanda/static/movie_posters', when I render it on HTML, it is loading the Static URL (127.0.0:8000/static) and then the location 'qanda/static/movie_posters' at the end. How do I make the image render correctly?
There are two pieces of how image url is calculated.
First in your settings.py you define MEDIA_ROOT. MEDIA_ROOT specifies an absolute folder on your computer where media will be stored. So for example for these settings:
MEDIA_ROOT = '/abs/path/to/media/'
and if you have a field
models.ImageField(upload_to='movie_posters')
then images will be stored at:
/abs/path/to/media/movie_posters/
/abs/path/to/media/movie_posters/poster.jpg <- example
This deals with where media is stored on your hard drive.
Second piece is how to calculate urls for these media files. For that you define MEDIA_URL in your settings.py. That essentially maps a URL to your MEDIA_ROOT location. So then if your MEDIA_URL is:
MEDIA_URL = 'http://localhost/media/'
Then if you want to access an image stored at movie_posters/poster.jpg which has an absolute path of /abs/path/to/media/movie_posters/poster.jpg, its URL should be http://localhost/media/movie_posters/poster.jpg. You can compute the URL by doing:
{{ MEDIA_URL }}{{ movie.poster }}
Please note that I am using MEDIA_URL instead of STATIC_URL. Those are not the same thing. Computing urls like that however is not very neat. Thats why Django's ImageField and FileField have an url attribute:
{{ movie.poster.url }}
Django will then compute the proper url depending on your MEDIA_URL setting.
Note:
For all of this to work, you have to have a separate media server running. Django does not serve any media files. In development it is only capable of serving static file (not same as media files). So in development one nice trick to serve media files is to use Python's simple web server. For that, open a new terminal (on Linux and Mac) or Command Prompt (on Windows) window/tab and navigate to your media folder. Then just execute the following command there:
python -m SimpleHTTPServer 8090
and make sure your setting is:
MEDIA_URL = 'http://localhost:8090/'
and then Python will serve your media files. That works nice for development.
If you want to serve your media just using the development server you can add this for the time being to your urls.py
urlpatterns = patterns( ...all your awesome urls...) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
you can define a custom template tag which returns the basename of the URL like this:
from django import template
import os
register = template.Library()
#register.filter
def getBasename(myURL):
return os.path.basename(myURL)
this should go in your custom template tags (eg. customTemplateTags.py) file within your templatetags directory of your app.
Then you can use the filter in order to get only the image filename, not the entire URL.
{% load customTemplateTags %}
<img src = "{{ STATIC_URL }}movie_posters/{{ movie.poster.url|getBasename }}"></a>

Flask static_folder hosted on S3

I am trying to reroute all of my /static content to host on Amazon S3. My first thought was to use global config['path'] throughout my jinja templates, but this won't work for external css and js files, plus it is kind of messy. I found the static_folder and static_url_path released in 0.7 and this seems like what I want. However, when I go to http://localhost:8000/static/img/abc.jpg it does not locate the files on S3. Am I using this feature right or is there some other way to do this?
Thanks!
I recently developed a Flask extension to deal with just this situation. It's called Flask-S3, and you can read the documentation for it here.
As an example, here is how you would integrate it into your Flask application:
from flask import Flask
from flask_s3 import FlaskS3
app = Flask(__name__)
app.config['S3_BUCKET_NAME'] = 'mybucketname'
s3 = FlaskS3(app)
You can use the extension to upload your assets to your chosen bucket:
>>> from my_application import app
>>> from flask_s3 import create_all
>>> create_all(app)
Flask-S3 is blueprint aware, and will upload all assets associated with any registered blueprints.
I wish the flask.Flask constructor's static_url_path argument would accept a full URI, but it screams about the path needing a leading slash when you try that. If it accepted it, you could just use url_for after setting static_url_path='http://my_s3_bucket.aws.amazon.com/' or so.
Another possible solution is to use a context processor. I believe this is the cleanest solution, but I don't have much experience with flask. It sure looks clean. Using a context processor, I pull the URL from the environment (I'm using heroku so it's wicked easy to set). Then the context processor makes the static_url variable available in my templates.
In app.py:
# Environment has STATIC_URL='http://my_s3_bucket.aws.amazon.com/'
#app.context_processor
def inject_static_url():
"""
Inject the variable 'static_url' into the templates. Grab it from
the environment variable STATIC_URL, or use the default.
Template variable will always have a trailing slash.
"""
static_url = os.environ.get('STATIC_URL', app.static_url_path)
if not static_url.endswith('/'):
static_url += '/'
return dict(
static_url=static_url
)
In the template:
<link rel="stylesheet" type="text/css" href="{{ static_url }}css/main.css" />
The result
<link rel="stylesheet" type="text/css" href="http://my_s3_bucket.aws.amazon.com/css/main.css" />
I know this is an old question but here's how I get around this issue.
Import Flask's url_for method under a different name (e.g., flask_url_for)
Create your own custom url_for method, which calls flask_url_for and then uses string replacement to add in your S3 bucket url.
I like this strategy because it's simple and intuitive to use, and the interface is exactly like the original url_for method.
from flask import url_for as flask_url_for
from flask import current_app
PRODUCTION_URL = 'https://s3.amazonaws.com/MY-BUCKET-NAME'
def url_for(path, **kwargs):
url = flask_url_for(path, **kwargs)
if url.startswith("/static") and not current_app.debug:
url = url.replace("/static", "", 1)
return PRODUCTION_URL + url
return url
what you are trying to accomplish is to be able to write
{{ url_for(app.static, file='img/abc.jpg', _external=True) }}
and have that resolve to a url in s3?
i believe that static_folder and static_url_path are setup so that if you call
app = Application('app', static_folder='foo', static_url_path='bar')
then going to
the above url_for would output
http://localhost:8000/bar/img/abc.jpg and it would look for static/img/abc.jpg in the filesystem.
i think what you want to do is potentially write a custom filter that would translate your path to an s3 url so that you could make a call something like
{{ 'img/abc.jpg'|s3_static_url }}
there's some documentation on that here: flask custom filters
What you need is the Amazon S3 public file URL instead of http://localhost:8000/static/img/abc.jpg. If its just a few files, maybe hardcode them in your template with the full URL or if you are going to have a local version for testing and use S3 on production site (like we do) then you can try the following method.
Define a new variable probably called STATIC_ROOT in the top of your base template (which other templates inherit), and use that as the file path prefix.
For example:
{% if app.debug %}
{% set STATIC_ROOT = url_for('static', filename='') %}
{% else %}
{% set STATIC_ROOT = 'http://s3.amazonaws.com/bucketname/' }
{% endif %}
This will give you the default path when you might be testing your application locally, and the public S3 url when in production (based on debug flag).
Using it:
<script src="{{ STATIC_ROOT }}js/jquery.min.js">

Categories

Resources