Below is my code in my main.html file:
<body>
<h1>mappymappy</h1>
<div id='map'></div>
<script>
mapboxgl.accessToken = '{{ mapbox_access_token }}'
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-73.9911, 40.7051],
zoom: 9.5
})
</script>
{% for center in drop_in_centers %}
<script>
new mapboxgl.Marker({ "color": 'red' })
.setLngLat([{{ center.longitude }}, {{ center.latitude }}])
.setPopup(new mapboxgl.Popup({ offset: 25 })
.setHTML("<h2>Drop-in Center</h2><h3>{{center.center_name}}</h3>"))
.addTo(map)
</script>
{% endfor %}
I want to move the scripts to a separate .js file.
However, in order to do that I have to figure out a way to
send the values mapbox_access_token and drop_in_centers to .js file
and make the values able to be used in the .js file.
How can I do this?
+) both mapbox_access_token and drop_in_centers are from views.py file.
Option 1) define vars in the template, pass them to js
views.py:
def my_view_function(request):
# define variables:
map_box_token = 'the_token'
drop_in_centers = 'the_drop_ins'
# pack context:
context = {
'map_box_token' : map_box_token,
'drop_in_centers' : drop_in_centers,
}
return render(request, 'template.html', context)
template.html:
<body>
...
<script>
var map_box_token='{{map_box_token}}';
var drop_in_centers='{{drop_in_centers}}';
</script>
<!-- include script.js after vars are defined -->
<script src="{% static 'script.js' %}"></script>
</body>
script.js:
console.log(map_box_token) // ex: use as needed
console.log(drop_in_centers) // ex: use as needed
Option 2) use ajax to retrieve data from views.py
views.py:
def my_view_function(request):
# define variables:
map_box_token = 'the_token'
drop_in_centers = 'the_drop_ins'
# pack context:
context = json.dumps({
'map_box_token' : map_box_token,
'drop_in_centers' : drop_in_centers,
})
return HttpResponse(context)
script.js:
function get_vars() {
// conduct ajax request:
$.ajax({
url : 'the_url',
success : get_vars_success, // reference to function below:
})
} $(document).ready(get_vars) // or call as needed
function get_vars_success(response) {
// unpack context:
var map_box_token = response.map_box_token;
var drop_in_centers = response.drop_in_centers;
// use as needed:
...
}
Related
I've created a map where I want to implement some kml files into it . If i harcode the url it works but im trying to pass it through a variable because Im dealing with many kml files in a for loop.
Even though the url path im getting in console is right i dont get the result i need.Any idea how to fix that?
view:
def map(request):
field_list = models.Field.objects.all()
context = {
"title": "Map",
"field_list": field_list,
}
template = 'agriculture/map.html'
return render(request, template, context)
If i hardcode the url it goes like this :
var polygon = omnivore.kml("{% static '../media/kml/user_admin/2022-04-07-2-Arnissa_cherry.kml' %}", ... );
I've tried doing it like this but even though the path Im getting is correct it seems django does not read the path(kml is the FileField in my model):
map.html
{% for field in field_list %}
$(".search_area").append(new Option("{{field.friendly_name}}")); //friendly name
var kmldir = "../media/" + "{{field.kml.name}}"
console.log(kmldir) // ../media/kml/user_admin/2022-04-07-2-Arnissa_cherry.kml
var polygon = omnivore.kml("{% static 'kmldir' %}", null, new L.GeoJSON(null, { //file url
style: function() {
return {
color: 'red',
transparent: true,
opacity: 1,
fillOpacity: 0.05
}}
}));
kml_arr.push([polygon, "{% static 'kmldir' %}"]); //file url
{% endfor %}
I tried a different approach and it worked
{% for field in field_list %}
{% with "../media/"|add:field.kml.name as fieldname %}
$(".search_area").append(new Option("{{ field.friendly_name }}")); //friendly name
var polygon = omnivore.kml('{% static fieldname %}', null, new L.GeoJSON(null, { //file url
style: function() {
return {
color: 'red',
transparent: true,
opacity: 1,
fillOpacity: 0.05
}
}
}));
kml_arr.push([polygon, '{% static fieldname %}']); //file url
{% endwith %}
{% endfor %}
So as mention in title, I'm trying to send my Django object to JavaScript so I can massage it in the front end. Let me show you the code (simplified).
views.py
def main_page(request):
contents = Contents.objects.all()
context = {
'contents' : contents
}
return render(request, 'main/home.html', context)
template
{% for u in all_ans_us_paginated %}
<div class="row">
<div class="col">
<div class="" id="{{u.id}}" onclick="DetailModal('{{u}}')">
</div>
</div>
</div>
{% endfor %}
...
<script>
function DetailModal(u) {
console.log('{{u.author}}');
console.log('{{u.body}}');
}
</script>
My intention is to show a modal when the click event is triggered. But putting the modal part aside, I can't pass data as parameter to JavaScript.
*I don't want to make any changes in the python code. Is it possible to do it only with HTML and JavaScript?
**JSON.parse(u) won't work, because u is string.
IN DJANGO
from django.shortcuts import render
from json import dumps
def send_dictionary(request):
# create data dictionary
dataDictionary = {
'hello': 'World',
'geeks': 'forgeeks',
'ABC': 123,
456: 'abc',
14000605: 1,
'list': ['geeks', 4, 'geeks'],
'dictionary': {'you': 'can', 'send': 'anything', 3: 1}
}
# dump data
dataJSON = dumps(dataDictionary)
return render(request, 'main / app.js', {'data': dataJSON})
IN JAVASCRIPT
app.js file :
var data = JSON.parse("{{data|escapejs}}");
for(var x in data){
// Write What You Want Here
}
if you want a clean view of the code use this way because javaScript considers dictionaries as separate objects
dataDictionary = [
["Laugh", "Cry"],
["Even", "Odd"],
["Hot", "Cold"],
["Light", "Dark"],
["Opposite", "Same"],
["Far", "Near"],
["Give", "Take"],
["Night", "Day"],
["Import", "Export"],
["Hard", "Easy"],
["Never", "Always"],
["Late", "Early"],
["Less", "More"],
["Male", "Female"],
["Happiness", "Sadness"],
["Fast", "Slow"],
["Old", "Young"],
["Boy", "Girl"],
["Up", "Down"],
["Left", "Right"],
["Rich", "Poor"],
["Love", "Hate"],
["Inside", "Outside"],
["Bad", "Good"],
["Short", "Tall"],
]
I am using https://github.com/fengyuanchen/cropper/blob/master/README.md as the cropper function. However, I want to submit field objects (in this case the title) and the cropped image. But I got an error on the admin. And of course, I have done the makemigrations and migrate before running the server
Error Picture
admin.py
from django.contrib import admin
from .models import Image
# Register your models here.
class ImageAdmin(admin.ModelAdmin):
pass
admin.site.register(Image, ImageAdmin)
models.py
from django.db import models
# Create your models here.
class Image(models.Model):
title = models.CharField(max_length=10)
image = models.ImageField(upload_to='images')
def __str__(self):
return str(self.pk)
forms.py
from django import forms
from .models import Image
class ImageForm(forms.Form):
image = forms.ImageField()
title = forms.CharField(
max_length=10,
widget=forms.TextInput(
attrs={
"class": "form-control",
"placeholder": "Title",
},
),
required=True
)
views.py
from django.shortcuts import render, redirect
from .models import Image
from .forms import ImageForm
from django.http import JsonResponse
from django.http import HttpResponseRedirect
def main_view(request):
form = ImageForm()
if request.method == "POST":
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
addimage = Image(
title=form.cleaned_data['title'],
image = form.cleaned_data['image'],
)
addimage.save()
else:
form = ImageForm()
context = {'form': form}
return render(request, 'photo_list.html', context)
photo_list.html
{% extends "base.html" %}
{% block javascript %}
<script>
console.log("Hello");
const imageBox = document.getElementById("image-box");
const confirmButton = document.getElementById("confirm-button")
const input = document.getElementById("id_image");
const csrf = document.getElementsByName("csrfmiddlewaretoken")
const imageForm = document.getElementById("image-form")
input.addEventListener("change", () => {
console.log("change")
const img_data = input.files[0]
const url = URL.createObjectURL(img_data)
imageBox.innerHTML = `<img src="${url}" id="image" width="500px">`
var $image = $('#image');
$image.cropper({
aspectRatio: 16 / 9,
crop: function (event) {
console.log(event.detail.x);
console.log(event.detail.y);
console.log(event.detail.width);
console.log(event.detail.height);
console.log(event.detail.rotate);
console.log(event.detail.scaleX);
console.log(event.detail.scaleY);
}
});
// Get the Cropper.js instance after initialized
var cropper = $image.data('cropper');
confirmButton.addEventListener('click', () => {
cropper.getCroppedCanvas().toBlob((blob) => {
const fd = new FormData()
fd.append('csrfmiddlewaretoken', csrf[0].value)
fd.append('image', blob, 'my-image.png')
console.log("append pass")
$.ajax({
type: "POST",
url: imageForm.action,
enctype: 'multipart/form-data',
data: fd,
success: function (response) {
console.log(response)
},
error: function (error) {
console.log(error)
},
cache: false,
contentType: false,
processData: false,
})
})
})
});
</script>
{% endblock %}
{% block page_content %}
<form action="/cropimage/" id="image-form" method="POST">
{% csrf_token %}
{{form}}
{% comment %} <button class="btn" id="confirm-button"> confirm </button> {% endcomment %}
<input class="btn btn-lg btn-primary btn-block" type="submit" value="Submit" id="confirm-button">
</form>
<div id="image-box" class="mb-3"> </div>
{% endblock %}
I was following this tutorial https://www.youtube.com/watch?v=oWd7SAuCIRM
Basically, I am making an album of images recorded with title, but this time with cropperjs. Any solutions or suggestions would be appreciated :).
Ahh silly me, after a week of finding solutions, I finally realize that I did not put and after deleting some of the database cache.
fd.append('title', $("input[name='title']").val())
on the getCroppedCanvas()
For those who had the same problem, please..
Ref :
How to append more data in FormData for django?
OperationalError, no such column. Django
https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
I have a form that when it is posted the content of console.html gets changed. for refreshing the page I used the following code but this does not refresh console.html
javascript
function autorefresh() {
// auto refresh page after 1 second
setInterval('refreshPage()', 1000);
}
function refreshPage() {
var container = document.getElementById("console");
container.innerHTML= '<object type="text/html" data="../../templates/snippets/console.html" ></object>';
//this line is to watch the result in console , you can remove it later
console.log("Refreshed");
}
index.html
<script>autorefresh()</script>
<div id="console" >
{% include 'snippets/console.html' %}
</div>
view.py
def index(request):
if request.method == "GET":
return render(request, 'index.html')
if request.method == "POST": # If the form has been submitted...
form=InputForm(request)
form.do_function()
return render(request, 'index.html')
I rewrote html with the help of jquery:
<script type="text/javascript" src="{% static "js/jquery.js" %}"></script>
<script>
function autorefresh() {
// auto refresh page after 1 second
setInterval('refreshPage()', 1000);
}
function refreshPage() {
$.ajax({
url: '{% url 'console' %}',
success: function(data) {
$('#console').html(data);
}
});
}
</script>
.
.
.
<script>autorefresh()</script>
<div id="console" ></div>
view.py
def console(request):
data=
return render(request, 'snippets/console.html',{"data": data})
console.html
{% for line in data %}
{{ line }}
{% endfor %}
and finally add console to urls.
urls.py
urlpatterns = [
path('', views.index, name='index'),
path('console', views.console, name='console'),
]
I hope you don't spend a day finding the solution :))
Say I have a controller like this:
public function showAction(Request $request, $id, $context = array())
{
$url = $this->getPlayUrl($id, $context);
//some code here}
I want to use the variable $url in a frontend js file like this :
var html = '<iframe src=\''+ url +'\' name=\'viewerIframe\' id=\'viewerIframe\' width=\'100%\'allowfullscreen webkitallowfullscreen height=\'100%\' style=\'border:0px\'></iframe>';
How am I supposed to make this happen? For the code above ,it gave me 'undefined url' error.
Thank you.
Another option would be to have your template call a controller action (so you can pass parameters as required), for example, like this example for using highchart.js:
{% block javascripts %}
{{ parent() }}
<script src="/js/highcharts.js"></script>
<script src="/js/exporting.js"></script>
<script type="text/javascript">
{{ render(controller('AppBundle:Default:script')) }}
</script>
{% endblock %}
In the controller it looks like this:
public function scriptAction() {
$reports = $this->get('app.reports');
$chart = $reports->getDistsFYToDate();
return $this->render('Default/script.js.twig', array(
'chart' => $chart,
));
}
and script.js.twig looks like this:
$(document).ready(function () {
var options = {
chart: {
type: 'line'
},
title: {
text: 'Distributions, FY{{ chart.fy }} to date'
},
xAxis: {
categories: [{% for category in chart.categories %}{{category|raw}}{%endfor%}]
},
yAxis: {
title: {
text: 'Distributions'
}
},
series: {{ chart.series|raw }}
};
$('#linechart').highcharts(options);
})
Maybe it's better if you use HTML5 data attributes: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes
In you view add some script tags and assign a javascript vraible to the twig variable. Don't forget to quote the twig (if required).
Firstly, I would ensure that the $url always had a value;
return $this->render('MyWebBundle:Player:show.html.twig', array(
'file' => $file,
'url' => (empty($url)) ? '' : $url,
'context' => $context,
'player' => $player,
'agentInWhiteList' => $agentInWhiteList
));
Something like;
<script>
var jsVar = '{{ url }}';
var html = false;
if (jsVar.length > 0) {
html = '<iframe src=\''+ jsVar +'\' name=\'viewerIframe\' id=\'viewerIframe\' width=\'100%\'allowfullscreen webkitallowfullscreen height=\'100%\' style=\'border:0px\'></iframe>';
}
// test html !== false before using it
</script>