django template cannot call javascript - javascript

I have the following django template and I have defined a button in it so that it calls the javascript function which I added to the page like below. I have the below issues:
1) If I bring the script tags to the header section nothings shows up.
2) If press the button I get the undefined error message. (Uncaught ReferenceError: postData).
What am I mssing here?
Thank you very much,
Mike
newproduct.html
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<title>New Product</title>
</head>
<body>
<p>Hellow</p>
Back
<h2>Please enter product details:</h2>
<button onclick="postData();">Send Post</button>
<form action="http://127.0.0.1:8000/newproduct/" method="post">
<p>{{ message }}</p>
{% csrf_token %}
{{ form.as_p }}
<input type="submit"/>
</form>
<script src="bower_components/jquery/src/jquery.js" type="text/javascript"/>
<script src="scripts/main.js" />
</body>
</html>
main.js
function postData ()
{
$.post('/newproduct', {name:'New Product JS', price:555, });
};

You've hard-coded the reference to postData in your HTML, but you've used it before you've defined it, since the JS isn't loaded until the end of the page.
You could fix this by moving the script to the top of the HTML, but it is better not to use JS directly in HTML like this. Rather, your script itself should use the jQuery dom-ready functionality to bind itself to the button event.
html:
<h2>Please enter product details:</h2>
<button id="my_button">Send Post</button>
main.js
$(function() {
$('#my_button').click(function() {
$.post('/newproduct', {name:'New Product JS', price:555, });
});
});

Maybe you're getting trouble handling the path url, instead use the full path, try something like:
{% static ‘path/to/file’ %}
In your settings.py
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
Remember that your static file dir is setted in the same level of your project.

Related

HTML/JavaScript - Replace onClick() (in HTML) with JavaScript (addEventListener not working)

I've tried a few solutions on here already, but I just can't seem to make them work.
I have a Flask app that uses HTML combined with JavaScript to display a handful of web pages.
Right now, I still have some inline code (which also prevents me from setting a proper CSP-Header), namely <... onClick="function()">.
Right now my HTML looks like this:
<html>
<head>
<...other stuff...>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script type="text/javascript" src="{{ url_for('static', filename = 'admin.js') }}"></script>
</head>
<body>
<div class="topnav">
<b>Logout</b>
AdminView
Show TAN
</div>
<...other stuff...>
</body>
</html>
JavaScript like this:
bunchOfFunctions
function logout() {
window.location.replace(URL_SLO)
}
function adminView() {
window.location.replace(URL_ADMIN_BASE)
}
function tanView() {
window.location.replace(URL_TAN)
}
I have attempted to import the Script at the bottom of the HTML file and then add Eventlisteners like so:
document.getElementById("logout").addEventListener("click", logout)
But all that does is do nothing when I click on the buttons again, not even an error.
On a related note, it'd be cool if I could download the Axios script and use it locally, since, y'know, security. But when I merely copy the content of the link and try to integrate it that way, the imports don't work.
Edit: Copied the working version of the snippet, not the broken one.
It now only works in one script, the other one doesn't.
tan.html:
<html lang="en">
<head>
<... other stuff ...>
</head>
<body>
<div class="topnav">
<b>Logout</b>
{% if isAdmin %}
<b>AdminView</b>
{% endif %}
</div>
<... other stuff ...>
<script type="text/javascript" src="{{ url_for('static', filename = 'tan.js') }}"></script>
</html>
and the corresponding JS file:
function logout() {
window.location.replace(URL_SLO)
}
function adminView() {
const URL_ADMIN_BASE = URL_BASE + "api/adminsans/";
window.location.replace(URL_ADMIN_BASE)
}
function mount() {
...other stuff
document.getElementById('logoutButtonTAN').addEventListener('click', logout);
document.getElementById('adminViewButtonTAN').addEventListener('click', adminView);
}
window.onload = mount
other stuff...
onclick
The onclick attribute fires on a mouse click on the element.
getElementById
Get the element with the specified ID
You must use ID
document.getElementById('logout').addEventListener('click', function(e) {
e.preventDefault();
alert('logout');
});
<div class="topnav">
<b>Logout</b>
AdminView
Show TAN
</div>

How to render a React component with Python Tornado template?

I'm trying to modify login page UI (with React) in JupyterLab, it seems like its server consists of Python Tornado and renders login.html as one of templates. (literally stored in templates directory. ...jupyter_server\templates\) It might also render others like 404.html, error.html respectively in terms of contexts.
I simply followed https://reactjs.org/docs/add-react-to-a-website.html like below so:
page.html
<head>
<meta charset="utf-8">
<title>{% block title %}Jupyter Server{% endblock %}</title>
:
:
<!-- We will put our React component inside this div. -->
<div id="like_button_container"></div>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<script src="https://unpkg.com/react#17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#17/umd/react-dom.development.js" crossorigin></script>
{% block login %}
{% endblock login %}
</body>
</html>
logint.html
{% extends "page.html" %}
{% block login %}
<script src="like_button.js"></script>
<script>console.log('This is Login page.')</srcipt> // logs shows fine
<h1>This is Login Page.</h1> // tag shows fine
{% endblock login %}
As I understand so far, when the url hit as login, login.html renders with appending its contents to page.html.
I was expecting the like_button.js component renders fine but it is the only thing excluded. The log and h1 are visible correctly meanwhile.
Have I missed something? any ideas welcome.
The src of the script isn't correct. In Tornado, you put your static files in a folder called static and then set the src like this:
<script src="{{ static_url('like_button.js')"></script>
If you put the file in a subfolder such as static/js/, then provide its relative path:
<script src="{{ static('js/like_button.js') }}"></script>

How to load jquery before all other javascript with master template

I am using a master template which roughly looks like this
<!DOCTYPE html>
<html lang="en">
<head>
// load css files
</head>
<body>
{% block body %}{% endblock %}
// load js files including jquery
</body>
</html>
Now all other sites for my app look like this
{% extends "master.html" %}
{% block body %}
// site content
{% endblock %}
for each site I have some specific javascript code, which I put at the end of the body block. But this means that this javascript is loaded before jquery is loaded (which is done in the master template). Since some of the javascript in the body tag requires jquery (like e.g. the $(document).read() function) I get errors. The simple solution is to include jquery in each body tag separately... however, that starts to undermine the point of the master template... is there any better solution?
thanks
carl
EDIT: Sorry I forgot to say that my current solution is to load jquery before the body, however, google pagespeed complains about this so I was looking for a better solution
If you have scripts in {% block body %} of extended files that dependens on jQuery; if so , it is recommended to load jQuery on head ofmaster.html
<!DOCTYPE html>
<html lang="en">
<head>
// load css files
//load jQuery --------------!!!!!!
</head>
<body>
{% block body %}{% endblock %}
// load js files excluding jquery
</body>
</html>

How to properly render FilteredSelectMultiple

I'm using FilteredSelectMultiple widget, but it just doesn't wanna look like the one in the admin.
The Javascript console show
Uncaught TypeError: undefined is not a function SelectFilter2.js:100
My form (the imported widget: django.contrib.admin.widgets.FilteredSelectMultiple)
class GroupPermissionForm(forms.ModelForm):
permissions = forms.ModelMultipleChoiceField(
queryset=Permission.objects.all(),
widget=FilteredSelectMultiple("verbose name", is_stacked=False)
)
class Meta:
model = Group
fields = ('permissions', )
The template
{{ group_perm_form.media }}
<form>
{{ group_perm_form.permissions }}
</form>
(I've tried {{ group_perm_form }} too but it didn't work, much to my surprise tho when I rendered the form with crispy I could filter the select input, however it was still broken up)
The order of my javascript files are the following:
jquery
django.js
form.media
This is the result btw
edit: the working template looks like this
<script type="text/javascript" src="/static/admin/js/jquery.min.js"></script>
<script type="text/javascript" src="/static/admin/js/jquery.init.js"></script>
{{ group_perm_form.media }}
<form>
{{ group_perm_form.permissions }}
</form>
<link rel="stylesheet" type="text/css" href="/static/admin/css/widgets.css" />
The admin JS widgets all have a dependency on the JSI18N script. Add this to in your template header:
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
Edit: Looks like you also need the jquery.init.js from static/admin/js, as jQuery is being namespaced to avoid conflicts and isn't passed to the SelectFilter2 script automatically.

Generate Javascript with custom tags in Django template

my problem is a bit unusual.
In my project I have a static js file with many functions defined there.
Then in each template I have a script tag where I define the necessary variables for this templates and call the function i need from the static file. And the view does nothing but rendering the template. So my template looks for example like :
{% extends "base.html" %}
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
{% block content %}
<script type="text/javascript">
$(document).ready(function(){
var first_var = 'foo';
var second_var ='bar';
my_function(first_var,second_var);
})
</script>
<div class="values"></div>
{% endblock %}
</body>
And the view simply looks like :
def my_view(request):
return render(request, 'my_app/my_template.html')
What I have to do, is instead of having to manually write the script tag in the template, have a custom template tag to which you can pass the variables needed and that will return the corresponding script. The reason i have to do that is to allow people who will use the app to avoid writing script and only wirte something like :
{% my_function 'foo' as first_var %}
I don't really know how to do this or if it's the right way to do so. The main point is using custom tags instead of wiritng the script, so how do you think this should be done ?

Categories