How to render a React component with Python Tornado template? - javascript

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>

Related

flask-assets - How to keep an specific app's static js files from being used by another app

I've done this in the past but I'm completely forgetting how I did it.
I'm developing a flask server that contains multiple apps with the static files bundled together but I want the js/css files in each app's static folder to be used only by the routes defined within that app's init.py file.
Lets assume I have an appA and appB:
app
- static // this contains my common js/css files
- apps
- appA
- __init__.py
- static // appA's js/css files
- appB
- __init__.py
- static // appB's js/css files
And I go to "localhost:8000:/appA" (assuming its a route i've defined). In its js file I have
$(document).ready(function(params) {
console.log('appA ready');
});
And if I go to "localhost:8000/appB" and it has in its js file
$(document).ready(function(params) {
console.log('appB ready');
});
No matter which route I run I will see "appA ready" and "appB ready" printed in the console.
Now I know that this makes sense. I've bundled and minified them together after all. But for the life of me I know I've used bundles in the past but was able to single out which app used what static file.
The point is to use a base static directory for common stuff and the app's static directory for app-specific things.
I have my assets configured thusly
from app.apps.appA import appA
from app.apps.appA import appA_js, appA_css
from app.apps.appB import appB
from app.apps.appB import appB_js, appB_css
flask_app.register_blueprint(appA)
flask_app.register_blueprint(appB)
globals_js = ('js/utils/jquery-3.4.1.min.js',
'js/utils/socket.io.js',
'js/utils/*.js')
globals_css = ('css/utils/common.css',
'css/utils/*.css')
assets = Environment(flask_app)
bundle_globals_js = Bundle(*globals_js + appA_js + appB_js, filters='jsmin', output='dist/local_js.js')
bundle_globals_css = Bundle(*globals_css + appA_css + appB_css, filters='cssmin', output='dist/local_css.css')
assets.register('base_js', bundle_globals_js)
assets.register('base_css', bundle_globals_css)
I feel like there's something about my asset bundle configuration that is wrong. Either that or it's how I'm importing the files in my html.
<head>
{% assets "base_js" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% assets "base_css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}"/>
{% endassets %}
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{title}}</title>
</head>
This is the header code being used by each specific html file appA and appB has.
There may simply be a fundamental misunderstanding here about how bundles are used.
I just want to specify a common static directory but be able to have my apps use their own js/css files in combination with those base files.
Could someone point me in the right direction?
Thanks!
I figured it out, although not in the way I remember doing it.
Rather than bundle all my static files together as a "base_js" or "base_css" bundle,
I created separate bundles with unique names.
bundles = {
'globals_js': Bundle('js/utils/jquery-3.4.1.min.js',
'js/utils/socket.io.js',
'js/utils/*.js',
filters='jsmin',
output='dist/local_global_js.js'),
'globals_css': Bundle('css/utils/common.css',
'css/utils/*.css',
filters='cssmin',
output='dist/local_global_css.css'),
'appA_js': Bundle(*appA_js,
filters='jsmin',
output='dist/local_appA_js.js'),
'appA_css': Bundle(*appA_css,
filters='cssmin',
output='dist/local_appA_css.css'),
'appB_js': Bundle(*appB_js,
filters='jsmin',
output='dist/local_appB_js.js'),
'appB_css': Bundle(*appB_css,
filters='cssmin',
output='dist/local_appB_css.css')
}
Now I specify a base html file that adds the global assets at the head
<head>
{% assets "globals_js" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% assets "globals_css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}"/>
{% endassets %}
</head>
<body>
{%block data %}{% endblock %}
</body>
</html>
and within appA or appB I extend that base html file and add my specific static assets within the extended code block.
{% extends "base.html" %}
{% block data %}
{% assets "appA_js" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% assets "appA_css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}"/>
{% endassets %}
{% endblock %}
Now appA/appB only load their respective static files.
Thanks!

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>

JavaScript doesn't run in Django

I'm trying to find out how to run JavaScript in Django to create chained forms. But at the first I want to find out how to even run JavaScript. I've created a simple main.js file which is in static forder.
I've added a path to main.js into the head of html. And the script have to run when the page is loaded (just to be sure that I can step forward).
I've put alert on the beginning of the function so I can see whether the js has been run. But I can't see no alert nor js in chrome inspect.
Could you guys tell me where is the problem?
main.js
$(document).ready(function(){
alert("OK")
$.ajax({
url: "get-possible-levels/",
type: "POST",
data: {language: $('#id_language').val()},
})
})
template:
{% extends 'base.html' %}
{% load static %}
{% block head %}
<script src="{% static "js/main.js" %}"></script>
{% endblock %}
{% block content %}
{% if user.is_authenticated %}
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ language_form }}
<button value="Update" type="submit">Submit</button>
</form>
{% endif %}
{% endblock %}
View:
#login_required
def create_order(request):
language_form = LanguageLevelForm(request.POST or None)
return render(request,'auth/jobs/create-job-test.html',context={'language_form':language_form})
EDIT: The main.js seems to be executed but it does not alert anything. I've checked inspect (and I've tried to put semicolon after alert('ok')) :
Your {% load static %} should be {% load staticfiles %}. After that try refreshing the page the way I described in my comment. BTW Are you actually including JQuery? Your question is about JavaScript. You should try to use a vanilla JavaScript alert before adding JQuery code just to troubleshoot it. If you can get that working try adding this to your <head>
<script src="jquery-1.12.0.min.js"></script>
Check if you have the path to the js file wrong.if your project folder has 2 folders inside (one with html files and 1 with Js files) then on your path with the ../ you go up one level on your folder and then go inside your javascript folder to find the file. So instead of
<script src="{% static "js/main.js" %}"></script>
write
<script src="../js/main.js"></script>

Flask|Jinjia2|Javascript: Passing Flask template variable into Javascript

What is the best way to pass a variable from a Flask template into the Javascript file? Here is my code
I have a simple view in my webapp:
#webapp.route('/bars')
def plot_d3_bars():
return render_template("bars.html", calendarMap = calendarMap)
I have a templated HTML file that looks like this:
{% extends "base.html" %}
{% block title %} Bar View {% endblock %}
{% block content %}
{% with calendarMap=calendarMap %}
{% include "buttons.html" %}
{% endwith %}
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="/static/css/d3.tip.v0.6.3.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- Custom codes for d3 plotting -->
<link href="/static/css/bars.css" rel="stylesheet">
<script> var calendarMap = {{ calendarMap|tojson }}; </script>
<script src="/static/bars.js"></script>
{% endblock %}
Previous answers told me that I could just jsonify the variable into a JSON object and I'll be able to use it. However, I want to use calendarMap inside of bars.js? but I am running into some scoping problems (i.e. bars.js doesn't recognized this calendarMap), what should I do instead?
Well, maybe it is too late, but here we go.
When you use a JavaScript code embedded in HTML code, this script will be rendered together with HTML. So any variable referenced in JavaScript, as a Flask variable, will be available in the page rendered.
When you use an external JavaScript file linked in HTML code, its code already exists, before the HTML be rendered. In some cases, I may say most of them, you aren't the owner of this file. So any variable referenced in JS file will not be rendered.
You may put this variable in HTML, via JS code, and consume this data with functions from foreign JS file.
Or you can render this JS file, before render the template, and use it. But I strongly recomend not to use this approach.

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