Use url_for of Flask in ajax function - javascript

I'm using Flask to create a little WebApp. In the file.py there is a
render_template('index.html', listaimmagini = listaimmagini)
where "listaimmagini" is a list of images name (According to Flask standard, the images are in static folder). Now in "index.html" i'm trying to show these images but seems that webapp doesn't found it in static folder (there is the usual broken icon for all my images)
Where is the error in my code?
Index.html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
window.onload = function(){
var img = [];
{% for imagelego in listaimmagini %}
img.push("{{url_for('static', filename = imagelego)}}");
{% endfor %}
var parent = document.getElementsByClassName('scroll')[0];
if(img.length>0){
parent.style.overflowY = 'scroll';
for(i=0;i<img.length;i++){
image = document.createElement('IMG');
image.src = img[i][0];
image.alt = '';
image.setAttribute("class", "scegli");
parent.appendChild(image);
}
</script>

Related

How to transmit Django variables to a Js file

As you can see in the code below, I have imported a <script type="text/javascript" src="{% static 'js/posts_lazy_loading.js' %}"></script> to my Index.html.
But there are Django variables in that JS file. like: {{ sizes }} and {{ urlsPosts }}, they go from Views.py to the Index.html.
Unfortunately Django doesn't see these variables in the JS file if I keep the JS as a separate file.
If I copy paste the JS right to the HTML without separating - everything works well.
How can I include these Django variables into the separate Js file?
Index.html:
<html>
{% load static %}
{% include 'head.html' %}
<body>
<header>
</header>
</body>
<footer>
<script type="text/javascript" src="{% static 'js/posts_lazy_loading.js' %}"></script>
</footer>
</html>
Views.py:
def index(request):
posts = Post.objects.all()
sizes = ''
urlsPosts = ''
for i in range(0, len(posts)):
if i == len(posts):
sizes = sizes + str(posts[i].thumbnail.width) + 'x'
sizes = sizes + str(posts[i].thumbnail.height)
urlsPosts = urlsPosts + posts[i].thumbnail.url
else:
sizes = sizes + str(posts[i].thumbnail.width) + 'x'
sizes = sizes + str(posts[i].thumbnail.height) + ' '
urlsPosts = urlsPosts + posts[i].thumbnail.url + ' '
return render(request,'index.html',{'posts':posts, 'sizes':sizes, 'urlsPosts':urlsPosts)
posts_lazy_loading.js:
var images = document.getElementsByClassName('cover_main_page'),
posts = document.getElementsByClassName('post'),
descriptions = document.getElementsByClassName('description'),
description_height = descriptions[0].clientHeight;
post_content = document.getElementsByClassName('post_content'),
loading = document.getElementsByClassName('dots_portoflio'),
sizes = "{{ sizes }}",
sizeslist = sizes.split(" "),
urlsPosts = "{{ urlsPosts }}",
urlslist = urlsPosts.split(' '),
ratios = [],
viewport_width = document.documentElement.clientWidth,
newwidth = 0,
margin = 3, //each post has 3vw margin left and 3vw margin right
mobile = 0,
mobilewidth = 94;
.... a lot of code here ....
Yup, django will generate this line as follows:
It won't open the JS as this will ask the browser to load the JS, to use django inside your JS, you have one of two options
Use {%include 'JSFILE'%} but in this case, your JS file shall be in the templates folder
Put the JS code itself in your HTML template.

Passing context variable from template to JavaScript file

This thread here discussed using variables in inline JavaScript in templates. If I have separate .js files containing scripts, sitting in static folder, such as following:
utils.js
const createButton = (buttonCount) => {
containerId = "myContainerId"
container = document.getElementById(containerId)
for (var i = 0; i < buttonCount; i++) {}
newButton = document.createElement("button")
newButton.value = "Test"
newButton.id = "testButton" + i
container.appendChild(newButton)
}
}
createButton(buttonCount)
mytemplate.html
{% extends "base.html" %}
{% load static %}
{% block title %}Testpage{% endblock %}
{% block content-main %}
<link href="{% static "css/mycss.css" %}" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.0/css/bulma.css" />
<div id="myContainerId"></div>
<script src="{% static 'js/utils.js' %}"> </script>
{% endblock %}
If I have a variable buttonCount passed into this template via a view function's context, how do I pass it to the utils.js file to be called by function createButton()?
views.py
def button_view(request):
...
buttonCount = 5
return render(request, 'mytemplate.html', {'buttonCount': buttonCount})
There can be a few ways:
Using Input Field
<input id="buttonCount" value = "{{buttonCount}}" style="display:none;">
Then read value of element with id= buttonCount in utils.js.
Inline Script **Not Suggested,Use Document.onload instead.
<script>
set_button_count({{buttonCount}});
</script>
But this will create a problem when your utils.js is not loaded yet.
document.onload
Place the script source in <head></head>
<script src="{% static 'js/utils.js' %}" defer> </script>
<script>
document.addEventListener('onload',function(
{set_button_count({{buttonCount}});
})
</script>
set_button_count() is to be placed in utils.js
Defer will ask browser to only fire document load when utils.js
is complete and it will be fetched and loaded after the document is
loaded.
Warning: Inline scripts are to be used with strict CSP (Content Security Policy).Any inline script can be given a src as nonce.
CSP can be done on Server Side on apache or Nginx which are very common web server/reverse proxy or you can also mention the same in HTML if you don't have control on that.
<meta http-equiv="Content-Security-Policy"
content="default-src 'self';
script-src 'self' 'nonce-{{nonce}}';">
and this nonce can be generated something like this:
import random,base64
def usersession_processor(request):
user = request.user
unbaked_nonce = '%32x' % random.getrandbits(16*8)
unbaked_nonce = unbaked_nonce.encode('utf-8')
baked_nonce = base64.b64encode(unbaked_nonce)
baked_nonce = baked_nonce.decode('utf-8')
Then <script src="{{nonce}}"></script> can be used for safe inlines.
I don't think this is recommended but you could do something like this if you're using the django template context. Put the script at the bottom of the page and include the buttoncount as a Django Templating Language variable. I don't think it's recommended to mix Django template variables with javascript though.
You can put a new block in your 'base.html' file, at the bottom inside the body tag like this:
{% block inline_javascript %}
{% enblock inline_javascript %}
Then inside the page you want the function to run on you put the script inside the same tags at the bottom of that page outside the 'block content' like:
{% block inline_javascript %}
<script>
const createButton = ({{ buttonCount }}) => {
containerId = "myContainerId"
container = document.getElementById(containerId)
for (var i = 0; i < {{ buttonCount }}; i++) {}
newButton = document.createElement("button")
newButton.value = "Test"
newButton.id = "testButton" + i
container.appendChild(newButton)
}
}
</script>
{% enblock inline_javascript %}

Django and javascript - how to use the value of dropdown box to access the static image stored on server using the static tag

{% load static %} line 1
<html> line 2
<head> line 3
<meta charset="UTF-8"> line 4
</head>
<body>
<select id="ddlViewBy">
<option value="Pranamasana.jpg">Pranamasana</option>
</select>
<img id='cat' crossorigin="anonymous" height = "620" width = "620"/>
<button onclick = "myfun()">button</button>
<script>
function myfun() {
var e = document.getElementById("ddlViewBy");
var strUser = e.options[e.selectedIndex].value;
document.getElementById("cat").src = "{% static 'Pranamasana.jpg' %}"; line 16
}
</script>
</body>
</html>
Even though I have a drop down box I am hard coding the name of the image to be accessed in line 16.
I want to know the way if I can use the string 'struser' so that the image selected by user can be displayed without hard coding.
Any help would be appreciated and thanks in advance.
I am using django and this is a html page in my project
Django template executes your code before the javascript does so you can't really use the javascript concatenate string adding. So the best way is to use {% get_static_prefix %}
var staticUrl = "{% get_static_prefix %}"
var strUsr = e.options[e.selectedIndex].value;
document.getElementById("cat").src = staticUrl + strUsr

Using blobs to store images as files via Javascript

I'm working on this project and ran into some complications using AWS S3 to host images. So I pivoted and decided to store the image as a Blob and let Javascript do the work of transforming the file into and out of the Blob, so I could then use AJAX and the API to store it in our DB. While this might be less than ideal, I'm still learning Javascript and hadn't worked with blobs a lot so I figured why not, time to learn.
My issue is that when I try to use a DataURI to show the image on the page it comes out as a string and not a DataURI, and therefore loads as a broken image. I haven't worked in ajax yet because I thought it better to take the image, turn it into an ascii string, put it in a blob, then get it back out before involving the API/server. Here is my html:
{% extends 'mp_app/base.html' %}
{% load staticfiles %}
{% block content %}
<div id="page-wrapper">
<pre id="fileDisplayArea"></pre>
<form id="picForm" method='post'>
{% csrf_token %}
<input type="file" id='imgFile' name="pic" accept="image/*">
<input type="submit" id='submitBtn'>
<input type="submit" id="showBtn">
</form>
<div id="imageDisplay"></div>
</div>
{% endblock %}
{% block javascript %}
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script type="text/javascript" src="{% static 'js/blob.js' %}"></script>
{% endblock %}
and my Javascript
//js file to turn an image into a blob, then store the blob in our API.
// next: retrive the blob and put it on the page
function textToImg(text) {
//get ascii string into binary then into an array then into a blob.
//had some strange issues using ArrayBuffer()
var file = new
Array(atob(document.getElementById('fileDisplayArea').innerText));
file = new Blob(file, {type:'image/*'});
let displayArea = document.getElementById('imageDisplay')
//currently doesn't seem to be loading as a DataURL. It's type is string and
//shows up as a broken image.
var reader = new FileReader();
reader.onload = function(event) {
var content = event.target.result;
img = new Image();
img.src = content;
displayArea.append(img)
console.log(img);
}
reader.onerror = function(event) {
console.error('error, file could not be read: ' +
event.target.error.code);;
}
reader.readAsDataURL(file);
// TODO get data via ajax to our DB our restful API
}
//turns an image into a blob
function imgToText() {
// get file elem and get image
let file = document.getElementById('imgFile');
let img = document.getElementById('imgFile').files[0];
let displayArea = document.getElementById('fileDisplayArea');
//open a file reader and read in file, then turn it from binary to ascii
var reader = new FileReader();
reader.onload = function(event) {
let contents = event.target.result;
//turn to ascii string
let asciiContents = btoa(contents);
//add ascii string to form
let form = {
'file': asciiContents,
}
displayArea.append(form.file);
};
reader.onerror = function(event) {
console.error('error, file could not be read');
}
//read file as a bit string
reader.readAsBinaryString(img);
// TODO send data via ajax to our DB our restful API
};
//add click event so that image is processed upon submit
$('#submitBtn').click(function(event) {
event.preventDefault();
imgToText();
});
$('#showBtn').click(function(event) {
event.preventDefault();
textToImg();
})
The img src reads as the blob string makes me think the something is wrong with the DataURI, perhaps it isn't getting the file in the proper format. I couldn't post a screen shot because I need a better reputation. Sorry this is so verbose but I wanted to try and make a quality post. Thank you!
I solved the issue. Will post here for future learners who may need this option.
textToImg() already has the string it needs, so all you need to do is get the string, add it to the file input element, (I added it as a 'value' attr), then let image.src = 'data:image/*;base64, + value attr. And you're good to go.

Javascript variable issue with Django

I am trying to use some javascript with my django code but have a small issue calling functions from the second js file.
I am using code from here https://github.com/mattdiamond/Recorderjs
I took the html file Matt made and removed the header and created a django template and then put the javascript files with my other static files. Those files (twitter bootstrap) all work fine.
If I open the sheet it loads fine with the record and stop buttons available. If you press them they are recorded in the log but any function that should be called in the recorderWorker.js is ignored. So I can not save the file or see it.
As far as I can tell it never calls the second javascript file. If I put alert boxes in the recorderWorker.js nothing happens but they work in the Recorder.js.
var WORKER_PATH = 'recorderWorker.js';
var Recorder = function(source, cfg){
I know it is not a problem with the code since I tested it using another Python webserver (SimpleHTTPServer) and it works great.
I have made no changes to the js files and only create this template for the html.
{% load staticfiles %}
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Live input record and playback</title>
<style type='text/css'>
ul { list-style: none; }
#recordingslist audio { display: block; margin-bottom: 10px; }
</style>
</head>
And then the html file
{% extends "base_record.html" %}
{% block content %}
<h1>Recorder.js simple WAV export example</h1>
<p>Make sure you are using a recent version of Google Chrome, at the moment this only works with Google Chrome Canary.</p>
<p>Also before you enable microphone input either plug in headphones or turn the volume down if you want to avoid ear splitting feedback!</p>
<button onclick="startRecording(this);">record</button>
<button onclick="stopRecording(this);" disabled>stop</button>
<h2>Recordings</h2>
<ul id="recordingslist"></ul>
<h2>Log</h2>
<pre id="log"></pre>
<script>
function __log(e, data) {
log.innerHTML += "\n" + e + " " + (data || '');
}
var audio_context;
var recorder;
function startUserMedia(stream) {
var input = audio_context.createMediaStreamSource(stream);
__log('Media stream created.');
input.connect(audio_context.destination);
__log('Input connected to audio context destination.');
recorder = new Recorder(input);
__log('Recorder initialised.');
}
function startRecording(button) {
// alert("start recording")
recorder && recorder.record();
button.disabled = true;
button.nextElementSibling.disabled = false;
__log('Recording...');
}
function stopRecording(button) {
// alert("Stopped recording")
recorder && recorder.stop();
button.disabled = true;
button.previousElementSibling.disabled = false;
__log('Stopped recording.');
// create WAV download link using audio data blob
createDownloadLink();
recorder.clear();
}
function createDownloadLink() {
recorder && recorder.exportWAV(function(blob) {
alert("download link")
var url = URL.createObjectURL(blob);
var li = document.createElement('li');
var au = document.createElement('audio');
var hf = document.createElement('a');
au.controls = true;
au.src = url;
hf.href = url;
hf.download = new Date().toISOString() + '.wav';
hf.innerHTML = hf.download;
li.appendChild(au);
li.appendChild(hf);
recordingslist.appendChild(li);
});
}
window.onload = function init() {
try {
// webkit shim
window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
window.URL = window.URL || window.webkitURL;
audio_context = new AudioContext;
__log('Audio context set up.');
__log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not present!'));
} catch (e) {
alert('No web audio support in this browser!');
}
navigator.getUserMedia({audio: true}, startUserMedia, function(e) {
__log('No live audio input: ' + e);
});
};
</script>
{% endblock %}
<body>
{% block content %}
{% endblock %}
<script type="text/javascript" src="{% static 'bootstrap/js/recorder.js' %}"></script>
</body>
</html>
Here is my settings.py
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/var/www/example.com/static/"
STATIC_ROOT = ''
# URL prefix for static files.
# Example: "http://example.com/static/", "http://static.example.com/"
STATIC_URL = '/static/'
# Additional locations of static files
STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static"
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
'/home/kevin/Programming/accent/static/',
)
I also faced similar issue where recorderWorker.js was not being accessed. However, the problem was solved when I did the following:
'static/filename/recorderWorker.js'
Note: Assuming that your JS file is located in the folder 'filename' which is in the static folder.
As far as Django is concerned, it looks for static files like JS files into the static folder, since you did not specify the path it did not load the file.

Categories