I had a Django project where i use Vue.js for some parts. I've translated all django parts and i now how to translate all Vue.js parts.
Language switcher is on Django template page and it's changing language in all django project and apps respectively.
I need to get current Django LANGUAGE_CODE and use it for setting Vue.js language.
This is a short version of app.js (somehow a point of entry for my Vue.js) where i import translations.json with a translations and setting Vue.js language
import Vue from 'vue';
import VModal from 'vue-js-modal';
import GetTextPlugin from 'vue-gettext';
import translations from '../../locale/translations';
const settings = {
apiKey: '',
lang: 'ru_RU',
coordorder: 'latlong',
version: '2.1',
};
Vue.use(GetTextPlugin, {
availableLanguages: {
en_US: 'American English',
ru_RU: 'Russian',
},
defaultLanguage: 'ru_RU',
translations,
});
If i change field defaultLanguage: 'LANGUAGE' in GetTextPlugin it will change the language for Vue.js. So i need to know how to get Django current language to set it here.
UPDATE
Did as dirkgroten say.
But now error in Vue appear "error 'LANGUAGE' is not defined no-undef"
base.html
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
<script>let LANGUAGE = {{ LANGUAGE_CODE }};</script>
<!DOCTYPE html>
<html lang="ru">
<head>
{% include 'chunks/head.html' %}
<title>{{ title }}</title>
</head>
<body>
{% include 'chunks/svg.html' %}
<div class="preloader">
<div class="preloader__icon"></div>
</div>
{% block content %}{% endblock content %}
{% block popup %}{% endblock popup %}
{% block script %}
{% include 'chunks/scripts.html' %}
{% endblock %}
</body>
</html>
Vue.js
Vue.use(GetTextPlugin, {
availableLanguages: {
en_US: 'American English',
ru_RU: 'Russian',
},
defaultLanguage: LANGUAGE,
translations,
});
Set a javascript constant in your base template:
{% get_current_language as LANGUAGE_CODE %}
<script>const LANGUAGE = "{{ LANGUAGE_CODE }}"</script>
Related
my python code:
def index(request):
body=list(Body.objects.all())
loads=list(Load.objects.all().order_by('length'))
badLoads=[]
goodLoads=[]
for load in loads:
if load.length>body[0].length or load.width>body[0].width or load.mass>body[0].mass:
badLoads.append(load)
else:
goodLoads.append(load)
goodLoadsLength=len(goodLoads)
context={
'body':body[0],
'loads':loads,
'badLoads':badLoads,
'goodLoads':goodLoads,
'goodLoadsLength':goodLoadsLength,
}
return render(request,'index.html',context)
html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>
{% if body %}
<p>body length: {{ body.length }}, body width: {{ body.width }}, body height: {{ body.height }}, body max mass, which can be taken: {{ body.mass }}</p>
{% else %}
<p>No parameters found</p>
{% endif %}
</div>
<div>
{% if loads %}
<ul>
{% for load in loads %}
<li>load id: {{ load.id }}, load length:{{ load.length }}, load width: {{load.width}}, load height: {{load.height}}, load mass: {{load.mass}}</li>
{% endfor %}
</ul>
{% else %}
<p>No loads are available.</p>
{% endif %}
</div>
<div>
{% if goodLoads %}
<ul>
{% for goodLoad in goodLoads %}
<li>load id: {{ goodLoad.id }}, load length:{{ goodLoad.length }}, load width: {{goodLoad.width}}, load height: {{goodLoad.height}}, load mass: {{goodLoad.mass}}</li>
{% endfor %}
</ul>
{% else %}
<p>No loads are available.</p>
{% endif %}
</div>
<div>
{% if loads %}
<ul>
{% for badLoad in badLoads %}
<li>load id: {{ badLoad.id }}, load length:{{ badLoad.length }}, load width: {{badLoad.width}}, load height: {{badLoad.height}}, load mass: {{badLoad.mass}}</li>
{% endfor %}
</ul>
{% else %}
<p>No loads are available.</p>
{% endif %}
</div>
<script>
const loadsLength="{{goodLoadsLength}}";
const goodLoads="{{goodLoads}}"
</script>
</body>
</html>
I would like to do a simple table with the help of javascript on the same page. I know I can do a table through html, but I would like to do it through Javascript, on the same page. But somehow I can see in script simple variables, like this one:
const loadsLength="{{goodLoadsLength}}";
But I cannot do list of items. The number of items can be different. So it should be going through for or forEach loop, but script does not give me any chance to get the members of a list in case of python(or array in case of javascript) into javascript block. If I try:
const goodLoads="{{goodLoads}}";
console.log(goodLoads);
It gives me:
[<Load: Load object (1)>]
Which seems like it sees the object in array. But when I try:
console.log(goodLoads[0].length);
or
foodLoads.forEach(item=>{
console.log(item.length)
})
It gives me: the object is undefined. I tried couple of more approaches like with for loop with for object in objects, or normal for loops with the step++ way. But the object is undefined.
I guess I don't understand how to get the list/array from html to script block. It should be seen as normal array of items. But I cannot get them. Can somebody pinpoint me to the answer? Thank you.
Use the Django built-in json_script (see documentation here) template tag to safely output a python object as JSON wrapped in a script tag. Then in your main JS script, you can parse the JSON object and do all standard operations with it.
In your template:
{{ goodLoads|json_script:"goodLoads"}}
In your main JS file:
let goodLoads = JSON.parse(document.getElementById('goodLoads').textContent);
Another issue is that you're passing QuerySet objects into the context variable goodLoads. It won't be very useful to have those objects in your JS file, because you cannot access the object field values. For that turn the QuerySet object into a dict before passing it to the context.
For example using queryset.values(),
def index(request):
body=list(Body.objects.all())
loads=list(Load.objects.all().order_by('length'))
badLoads=[]
goodLoads=[]
for load in loads:
if load.length>body[0].length or load.width>body[0].width or load.mass>body[0].mass:
badLoads.append(load.values()) #converting to dict here
else:
goodLoads.append(load.values()) #converting to dict here
goodLoadsLength=len(goodLoads)
context={
'body':body[0],
'loads':loads,
'badLoads':badLoads,
'goodLoads':goodLoads,
'goodLoadsLength':goodLoadsLength,
}
return render(request,'index.html',context)
in my base.html template, I write a function. Can I call it from another template?
I tried like this. It doesn't work.
base.html:
<!-- ...code... -->
<script>
function registration(){
if(document.getElementById("registration").className==='hide'){
document.getElementById("registration").className='show'
}else{
document.getElementById("registration").className='hide'
}
}
</script>
another template
{% extends 'base.html' %}
{% block body %}
<script>
//if i re write the function here, it works
registration()
</script>
{% endblock body %}
You can try like this in your base.html
<html>
<head>
<!---Here all the CSS links --->
{% block css %}
{% endblock css %}
<head>
<body>
{% block body %}
{% endblock body %}
</body>
{% block script %}
//write your script here
{% endblock script %}
</html>
in other template you have to just do like this
for example about.html
{% block body %}
{% endblock body %}
I am trying to implement Webpack Encore in my Symfony Project. I just added SweetAlert2 with node (npm i sweetalert2 --dev).
My "problem" is that I don't realize how to properly use this package once installed. I've been reading other questions but I don't understand where do I need to import it.
So far I've tried:
Creating a file inside /assets/js/swal.js. Also, I have tried with ES5 as well:
import Swal from 'sweetalert2';
export const swal = (message, type) => {
Swal.fire({
position: 'top-end',
icon: type,
title: message,
showConfirmButton: false,
timer: 1500
});
}
Add it to webpack.config.js as an Entry Point:
.addEntry('app', './assets/js/app.js')
.addEntry('swal', '/assets/js/swal.js')
Add it as an asset to the template with <script src="{{ asset('js/swal.js') }}"></script>. Maybe is worth to mention that I did try all the paths and PHPStorm does not recognize any of them.
Print the function or class inside Twig template:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
{{ encore_entry_link_tags('app') }}
</head>
<body>
{% block body %}{% endblock %}
{{ encore_entry_script_tags('app') }}
{% block javascripts %}{% endblock %}
{% if app.flashes is not empty %}
<script>
console.log(swal);
</script>
{% endif %}
</body>
</html>
I also tried importing it with require() but require is not idefined.
What should I do to implement this function and render it in the Twig template?
You can only import modules inside javascript (or typescript, etc) files.
let's say you have a function inside the script of the twig template:
<script>
function doSomethingBasic() {
// do your thing here, then alert the user using Swal
}
</script>
What you should do is export everything inside the javascript tag into a new .js file, inside the /assets folder.
After you create a new file inside the /assets folder with any name you want, you should add that entry to the webpack.config.js.
For example:
You created the newJavascript.js inside /assets.
Inside webpack.config.js:
.addEntry(`literallyAnyName`, `/assets/newJavascript.js`)
Then, in your twig template, substitute your script tags for this (must be the name you put in the webpack.config.js, in this case literallyAnyName):
{{ encore_entry_script_tags('literallyAnyName') }}
With this, you can import Swal in your newJavascript.js
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}
{{ encore_entry_link_tags('literallyAnyName') }}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
{% set flashes = [] %}
{% if app.flashes is not empty %}
{% for label,message in app.flashes %}
{% set flashes = flashes|merge([{
'type': label,
'message': message
}]) %}
{% endfor %}
{% endif %}
<div id="flashes" data-flashes="{{ flashes|json_encode|e('html_attr') }}"></div>
{% block javascripts %}
{{ encore_entry_script_tags('literallyAnyName') }}
{% endblock %}
</body>
</html>
newJavascript.js:
const flashes = JSON.parse(document.querySelector(`#flashes`).dataset.flashes);
// Maybe reduce the flash object into one message using flashes.reduce;
if(flashes.length > 0) {
const msg = flashes.reduce(/* your logic here */);
Swal.fire({
position: 'top-end',
icon: type,
title: msg,
showConfirmButton: false,
timer: 1500
});
}
This will trigger the second the page loads. You can make a button trigger as well if you need to.
I would like to make a "component" (several actually, but let us start with one). That is I would like to have a template file, which itself may include javascript. Then I would like to be able to include that "component" in whatever (other) Django template file.
Importantly: in the base.html I include utility javascript (like jquery or bootstrap or whatever) and I want those things to be in scope in the component's javascript.
Are there other achitectural ways of achieving this?
Here is a visual of one Django template:
and when an item is clicked, it will update the other part of the page, allowing that template and its included JS to run with access to the rest of the page's javascript.
Here is some code to go along with it (I mistyped base to baste, so I went with the theme):
models.py
class CommonTask(models.Model): ## nothing special
name = models.CharField(max_length=30, default='yummy')
urls.py
app_name = 'food'
urlpatterns = [
## the list view on the left
url(r'^edible/?', views.EdibleList.as_view(), name='edible'),
## the partial on the right
url(r'^billable/edit/(?P<jid>[a-zA-Z0-9-\w:]+)/?', views.EdibleEdit.as_view(), name='edibleEdit'),
views.py
class EdibleList(ListView):
template_name = 'food/edible-list.html'
def get_queryset(self):
return Dish.objects.filter('edible'=True)
class EdibleEdit(UpdateView):
form_class = EdibleForm
template_name = 'food/edible-edit.html'
def get_initial(self):
… # for the form/formset info
def get_object(self):
return get_object_or_404(Dish, pk=self.kwargs['pk'])
baste.html
<!DOCTYPE html>
{% load static %}
<html lang="en" xml:lang="en" dir="ltr" xmlns= "http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" href="{% static "css/main.css" %}">
{% block meta_tags %}{% endblock meta_tags %}
{% block scripts-head %}{% endblock scripts-head %}
<title>Edibles - {% block title%}{% endblock title%}</title>
{% block extra_head %} {% endblock extra_head %}
</head>
<body>
{% block content %} {% endblock content %}
{% block scripts %} {% endblock scripts %}
<script>
{% block script-inline %} {% endblock script-inline %}
</script>
<footer> FOOTER </footer>
</body>
</html>
list.html
{% extends "baste.html" %}
{% load static %}
{% block title%}Edible List - {{dish.name}} {% endblock title%}
{% block extra_head %}
<link rel="stylesheet" href="{% static "food/food.css" %}">
{% endblock extra_head %}
{% block script-inline %}
console.log('This works, as it is in the views original compiled template');
console.log('This does not work, as it relies on the partial to be loaded, but
the partial isn't loaded yet, and this wont update after the partial is loaded);
var interpuncts = document.getElementsByClassName("interpuncts");
for (let i=0; i < interpuncts.length; i++){
interpuncts[i].onclick=function(event){
console.log('gh1');
};
};
// showing the right partial when clicked
pane = document.getElementById("edible-single");
showPane = function(link) {
fetch(link).then(function(response) {
return response.text();
}).then(function(body) {
pane.innerHTML = body;
});
};
let edibleLinks = document.querySelectorAll("a.edible-link");
edibleLinks.forEach(function(edibleLink) {
edibleLink.addEventListener('click', function(e){
e.preventDefault();
showPane(edibleLink.getAttribute('href'));
});
});
{% endblock script-inline %}
{% block scripts %} {% endblock scripts %}
{% block content %}
{% include "food/nav.html" with currentView="edibleList" %}
<div class="container-fluid">
<h1 class="text-center">Edible Dishes</h1>
<hr>
<div class="row scrollable-row">
<div class="col-3 scrollable-col">
<table class="table">
<tbody>
{% for dish in dish-list %}
<tr class="d-flex">
<td class="col">
<a class="edible-link"
href="{% url 'food:ediblebleDetail'
pk=dish.pk %}"
data-pk="{{dish.pk}}">{{dish.name}}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="col-9 scrollable-col" id="edible-single"></div>
</div>
</div>
{% endblock content %}
editPartial.html
{% load static %}
{# no blocks work in this, because it can't extend the list.html, because the view #}
{# can't render to endpoint(sibling) templates at the same time #}
{# {% block * %} #}
<script>
console.log('This won\'t run, as it is loaded separately as just an inclusion
text from the list AJAX call.')
$(document).ready(function() {
console.log('This can\'t work because it relies on $ to be accessible, which it is not')
var interpuncts=document.getElementsByClassName("interpuncts");
for (let i=0; i < interpuncts.length; i++){
interpuncts[i].onclick=function(event){
console.log('I can not get a handle on the partial template items after
they are loaded as a partial');
};
};
});
</script>
<div class="container">
Dish - {{dish.name}}
<hr>
<form action="{% form url %}" method="post">
{% csrf_token %}
{{ form }}
{# Some element(s) that needs some javascript to act on it, more comprehensive than #}
{# bootstrap show/hide can do #}
<div class="interpuncts">
··· Do something with this element
</div>
<input class="btn btn-primary pull-right" type="submit" value="Save">
</form>
</div>
NOTES:
This is similar to Rails' partials if I remember, and definitely doable in 'Angular/Ember'. I think this boils down to some architecture, or package I am unaware of and can't find documentation. I am unsure of it is doable with inclusion tags.
i'm using nunjucks (gulp) as templating language and i want to build a dynamic page template.
This is my Json:
"pages": [
{
uname: "Welcome",
title: "Page 1 Headline"
},
{
uname: "About",
title: "Page 2 Headline"
}
]
Currently i have a static page (html) template for each page:
{% extends "layout.html" %}
{% set active_page = "Welcome" %} //<- This needs to be dynamicly
{% block content %}
<h1>{{ page[0].title }}</h1> //<- This needs to be dynamicly
My first thought was to read the url parameters but i couldn't solve it in this way.
Any suggestions?
The solution was simple!
Need to do this:
index.njk
<!-- set title !!! -->
{% set title = 'home page' %} <!-- set title !!! -->
{% extends "layout.njk" %}
{% block header %} {% include "parts/header.njk" %} {% endblock %}
{% block main %}
<main class="main">
<!-- content -->
</main>
{% endblock %}
{% block footer %} {% include "parts/footer.njk" %} {% endblock %}
page1.njk
<!-- set title !!! -->
{% set title = 'page1' %}
{% extends "layout.njk" %}
{% block header %} {% include "parts/header.njk" %} {% endblock %}
{% block main %}
<main class="main">
<!-- content -->
</main>
{% endblock %}
{% block footer %} {% include "parts/footer.njk" %} {% endblock %}
layout.njk
<!-- layout.njk -->
<html lang="en">
<head>
<!-- here is the compiled title -->
<title>{{ title }}</title>
<link rel="stylesheet" href="styles/style.css">
</head>
<body class="page">
{% block header %}{% endblock %}
{% block main %}{% endblock %}
{% block footer %}{% endblock %}
</body>
</html>
If you are hoping to pass the data from data.json file
first you need to use someway to specify the page name in the data file itself.
Then you have to set the page name as a variable in the nunjucks page.
Now you can use this variable name to get the data relevant to the
page you are working in.
data.json
{
"pages": {
"welcome": {
"uname": "Welcome",
"title": "Page 1 Headline"
},
"about": {
"uname": "About",
"title": "Page 2 Headline"
},
}
}
index.njk
{% set pageName = 'welcome' %}
{% extends "layout.html" %}
{% set active_page = "Welcome" %}
{% block content %}
<h1>{{ page[pageName].title }}</h1>
{% macro inc(file, folder) %}
{% if folder %}
{% set folderPATH = folder %}
{% else %}
{% set folderPATH = file %}
{% endif %}
{% set path = folderPATH + "/" + file + ".njk" %}
{% include path %}
{% endmacro %}
{{ inc("menu") }} // {% include "menu/menu.njk" %}
{{ inc("content") }} // {% include "content/content.njk" %}