Using a variable to for loop using django - javascript

I'm very new to python and django framework. I'm facing a minor issue of not being able to assign a variable to my for loop.
In my html file there are buttons and a list (rendered using a loop).
for ex:
Buttons
<li><a class="layer-item" href="#" onclick="selectLayer('base')" title="Base layer">Base layer</a></li>
<li><a class="layer-item" href="#" onclick="selectLayer('soil')" title="Soil layers">Soil layers</a></li>
Inside script tags i'm updating the variable value as
<script>
var layerType = "";
function selectLayer(layer){
layerType = layer;
}
</script>
Also i have a loop like following in the same html file
{% for layer in base %}
<div class="col-4">
<span class="base-layer-title d-block">{{layer.title}}</span>
</div>
{% endfor %}
Here i want to replace base according the button clicked.
For ex:
<a class="layer-item" href="#" onclick="selectLayer('soil')" title="Soil layers">Soil layers</a>
Clicking on the above button should make the for loop as
{% for layer in soil %}
<div class="col-4">
<span class="base-layer-title d-block">{{layer.title}}</span>
</div>
{% endfor %}
From i read you can do something like this to assign a value to a variable.
{% with name="World" %} But not sure how to implement it in my issue.
Any help is appreciated

Also i have a loop like following in the same html file
{% for layer in base %}
{{layer.title}} {% endfor %}
Here i want to replace base according the button clicked.
In short, Django is a server-side framework and it cannot directly respond to any client-side activity. You cannot do it effectively without client-side libraries like React, JQuery, etc.
Workaround 1
You can make a new request to the server on click and re-render the entire page with new parameters.
urls.py
path('my_pattern/<slug:my_layer>', myview)
views.py
def myView(request, my_layer):
# your logics
base = get_layer_data(my_layer) # <-- logic to get list dynamically
return render(request, 'my_template.html', context={'base':base})
my_template.html
{% for layer in base %}
<div class="col-4">
<span class="base-layer-title d-block">{{layer.title}}</span>
</div>
{% endfor %}
...
<a class="layer-item" href="/my_pattern/soil" title="Soil layers">Soil layers</a>
<a class="layer-item" href="/my_pattern/some_other_layer" title="Some other layers">Soil layers</a>
...
The base will have dynamically generated data on every request.
Workaround 2
You can, however, render all the data on the page and control it using collapse in bootstrap https://getbootstrap.com/docs/4.5/components/collapse/

Related

Open the xx.html file based on drop down menu from Navigation bar, code is written in Django-Python

The code is written in Django-Python. The project is created using the models in Django and shown in navigation as dropdown menu.
The drop-down menu is shown using the Django-HTML as shown in following way:
This code works well for dropdown menu. but I want to open the different project url based on click.
I am not sure exactly how to assign id and use javascript to code do onclick bsed html loading !!
I have tried some javascript code, but I am novice.. so If I put here.. it would be more confusing.
<div class="dropdown-menu" id="navbarDropdown">
{% if project_records %}
{% for p in project_records %}
{{ p.pName }}
{% endfor %}
{% endif %}
</div>
I expect that projectB.html will be loaded if click projectB in dropdown menu in navigation bar.
Add the href attribute in anchor tag appropriately. Assuming http://someurl/ is the prefix and the project name is the suffix of your project URLs, you may form the target URL in a variable and use it. Here is your modified code:
<div class="dropdown-menu" id="navbarDropdown">
{% if project_records %}
{% for p in project_records %}
{% with project_url="http://someurl"|add:p.pName %}
{{ p.pName }}
{% endfor %}
{% endif %}
</div>

JavaScript Function Doesn't Work On Django

When the first page is loaded, I want the user to come across all the music, but if he selects a list from RadioButton, I only want the music in that list, but the javascript function doesn't work.
Let me add that I don't normally know JavaScript, but I need to use it.
<div style = "margin-top : 100px;"class = "container">
{% for table in tables %}
<input type="radio" name="list1" onclick="mL('{{table}}')"> {{table}}
{% endfor %}
<div align="center">
<audio class="my_audio" controls="controls" autoplay="autoplay" style="width:500px;"></audio>
<ul>
{% for table in tables %}
{% for music in musics %}
<li style="list-style-type:None">
<a id="{{table}}" href="javascript:void(0);" onclick="playSong('{{music}}')">{{music}}</a>
</li>
{% endfor %}
{% endfor %}
{% for music in musics %}
<li style="list-style-type:None">
<a id="default" href="javascript:void(0);" onclick="playSong('{{music}}')">{{music}}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
<script> function mL(x)
{
{% for table in tables %}
if (x=={{table}})
document.getElementById("{{table}}").style.display="block";
document.getElementById("default").style.display="none";
{% endfor %}
else
document.getElementById("{{table}}").style.display="none";
document.getElementById("default").style.display="block";
return;
}
</script>
This isn't a Django issue, it's purely about the JavaScript (or should be).
Here are some problems with your code:
In HTML, the id attribute should be unique in the document. You seem to have many <a> tags with the same id. Use the class attribute, or even better use your own data attribute like data-table.
You can code generate JavaScript using Django template tags like you have, but I think it's a bad idea because it's very hard to reason about how the code will work. Don't use {% for %} inside the <script> block.
JavaScript doesn't use spaces for code blocks like Python does. You need to use braces { } instead.
Once those things are fixed, use the debugging console in your browser (F12 in Firefox and Chrome). It will let you see any syntax errors, and you can even run code in the console to see how things like document.getElementById work.

Flask - Component templates structure?

I've been experimenting with a Flask template structure to resemble a component workflow. This is inspired by Vue.
Some key ideas :
Each page is treated as a component
A component is just a folder containing all necessary files inside it (except ones that are common)
Each component is encourageg to have several HTML files to avoid large files, we will be using Jinja's include to "bundle" them
togheter
Avoid javascript, or at least, loading unnecessary javascript, each page will include only what's necessary
Here's an example :
The route for PageExample would be the following :
app.route('/example'):
return render_template('PageExample/html.html')
And PageExample/html.html :
{% extends 'base.html' %}
{% block content %}
<div class="tab" id="tab1">
{% include 'PageExample/tab1.html' %}
</div>
<div class="tab" id="tab2">
{% include 'PageExample/tab2.html' %}
</div>
{% endblock %}
PageExample/tab1.html (tab2 follows the same logic)
<!-- block header is in base.html -->
{% block header %}
{{ super() }}
<script src="{{url_for('components', 'PageExample/tab1.js')}}">
{% endblock %}
<div class="tab-content">
Some content here that uses the tab1.js javascript
</div>
So, what's the question ?
I have limited experience with Flask, so I'm not sure if this idea is sound, it seems hacky but it makes developing pages easier, especially with multiple people (the little javascript a page might need can be done in any way). Also increased loading speed by a ton.
Dos this work? Is this structure reccomended? Are there any flaws to it? What sort of problems could I run into? Any recommendation to do it better? Is this already done nowadays in Flask? I couldn't find any examples of a Flask app done this way (specially the Jinja stuff using lots of includes)
I'm currently not at my main computer, so I'll update this later if need be, but if your included html files referenced any data that is stored in the backend then you'd also need to make sure you reference the exact location there as well.
For example:
If you need the first name property from a User class it would be
{{ User.firstName }}
Not only that, but the tab template will also need to be supplied this User.firstName variable, which isn't done implicitly.
You will need to create what is called a Blueprint then a View and tell the view to make the User.firstName variable available to PageExample/tab1.html
tabs.py
import User
from flask import Blueprint, render_template
import """other flask dependencies needed"""
bp = Blueprint('index', __name__, url_prefix='/')
def tabData():
"""data to process"""
render_template("PageExample/tab1.html", User=User)
In that same tabs.py file, you can also write a view for tab2.html as well as html.html. Should be noted that I'm assuming that the contents of PageExample are for the index of the website and that they will all be rendered on that same page.
Also, It seems like your tabs will be in the content/body of the html but it will also render the blocks of base.html and add the defined scripts inline with the body of html.html. Instead, it should be referenced in the html.html file itself
html.html
{% extends 'base.html' %}
{% block header %}
{{ super() }}
<script src="{{url_for('components', 'PageExample/tab1.js')}}">
{% endblock %}
{% block content %}
<div class="tab" id="tab1">
{% include 'PageExample/tab1.html' %}
</div>
<div class="tab" id="tab2">
{% include 'PageExample/tab2.html' %}
</div>
{% endblock %}
with tab1.html being
<div class="tab-content">
Some content here that uses the tab1.js javascript
</div>
Obviously, this is just the surface of what you will need to know about flask. Think the bottom line is that it can work. Although I would suggest that your put all resources such as JS and CSS in a separate folder and reference those resources from those locations.
For more information on Flask and how you can utilise it, check out the Flask Tutorial here:
http://flask.pocoo.org/docs/1.0/tutorial/

How can i know which link i clicked in an HTML

Hi i am using PHP and Twig to create a blog for practice, i want to be able to access a post for it to display completely on a new url, for this i use a route to '/indiv' which using a controller renders a new page, what i want is to be able to access any post and display it using only one '.twig' file, however i don't seem to find a way to find out wich post was clicked, i know it has something to do with $_GET or $_POST however i don't know how to get the id of the post, some help would be greatly appreciated :)
{% extends "layout.twig" %}
{% block content %}
{% for blogPost in blogPosts %}
<div class="blog-post">
<a href={{'/indiv' | url}}> <h2> {{blogPost.title}} </h2> </a>
<form method="get">
<lable for="id"></lable>
<input class="btn btn-primary" type="submit" value="GotoPost">
<a href={{'/indiv' | url}}> </a>
</input>
</form>
<p> Jan 1, 2020 by Alex </p>
{% if blogPost.img_url %}
<div class="blog-post-image">
<img src={{blogPost.img_url}} alt="">
</div>
{% endif %}
</div>
{% endfor %}
{% endblock %}
one way:
you have to alter your route so it accepts a parameter
/indiv/{id}
and in your html you send the id of the clicked post
<a href='/indiv/{{blogPost.id}}>
another way:
as i can see in your code, you are sending data in a form so you can send the id of the post as well in the form using <input type="hidden" value="{{blogPost.id}}"
i never used Twig so the syntax might be wrong but this is the logic to be used.

changing class of element in django template using javascript function

In my django template I have some Event items listed using a for loop.The event has an associated date_of_occurrence attribute which is a python DateTime.I need to make the background for the event red ,if the datetime is less than current datetime.
I thought of doing it like this
In template
<ul>
{% for event in events %}
<div id="event_div"
<li>
event.name<br>
event.date_of_occurrence
</li>
</div>
{% endfor %}
</ul>
In css
.pastevent{
background-color:red;
}
I need a javascript function to set the class of element with id event_div to pastevent.Can someone tell me how this function can be implemented?
As I understand the function is not fired by any click event ,but when page loads. How will the datetime value of event passed from the template to do the comparison to the current javascript date?
You wouldn't necessarily have to use javascript to do this. There are a couple of different options using the template tags.
The simpler approach (and more crude) would be to render the current datetime to the template as eg. current_date then do a logic check in your template.
{% for event in events %}
{% if event.date_of_occurrence < current_date %}
<div id="pastevent">
{% else %}
<div id="event_div">
{% endif %}
<li>
event.name<br>
event.date_of_occurrence
</li>
</div>
{% endfor %}
The other option would be to create a custom template filter that returns whether the event was in the past or not and apply the same logic as above.

Categories

Resources