Using boostrap in django template correctly - python

I have this hierarchical order of models: courses, study programmes, departments and faculties. I have 2 columns in bootstrap. The first column lists all faculties, with their specific departments and the study programmes of each department. The second column lists all courses. I want that when someone clicks on a faculty, to display the specific courses for that faculty in the second column by replacing all courses, same for departments or study programmes. Now, I tried something, but I don't know how to achieve this result. I don't know how to list courses for each faculty, as you can notice, I put faculties.0 as a test.
<script>
$('#btnClick').on('click', function () {
if ($('#1').css('display') != 'none') {
$('#2').show().siblings('div').hide();
} else if ($('#2').css('display') != 'none') {
$('#1').show().siblings('div').hide();
}
});
</script>
<div class="row">
<div class="col-md-3">
<div class="jumbotron">
<h4>Search courses</h4>
<hr>
<br>
<ul>
{% for faculty in faculties %}
<li id="btnClick">{{ faculty.name }}</li>
<ul>
{% for department in departments %}
{% if department.faculty == faculty %}
<li>{{ department.name }}</li>
<ul>
{% for study in studies %}
{% if study.department == department %}
<li>{{ study.name }}</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
</ul>
</div>
</div>
<div class="col-md-9">
<div class="jumbotron">
<div id="1">
<h3>All courses</h3>
<ul>
{% for course in courses %}
<li>
<a id="first" href={{ course.slug }}>{{ course.name }}</a>
</li>
{% endfor %}
</ul>
</div>
<div id="2" style="display:none;">
<h3> {{ faculties.0 }} courses</h3>
<ul>
{% for course in courses %}
<li>
<a id="first" href={{ course.slug }}>{{ course.name }}</a>
<p>chinchin</p>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
This is how it looks like now: https://i.imgur.com/fLq7MH2.png

Ok, so I think part of your problem is that you want a second, hidden div, with Faculty specific courses listed, however your current HTML template is only ever going to give you one hidden div, with a single faculties courses in. You need to have one hidden div per faculty.
NB: I wouldn't do it this way using hidden divs, personally I'd use Bootstrap's tab/pill style.
Anyway, I think the below should give you the sort of result you are looking for. Obviously I can't test it with your models. I've changed the template to use the related objects notation rather than your if == style.
I've also changed the jQuery a bit. Hopefully it's ok, although it will have the effect that the #1 div will only be visible before any links are clicked.
UPDATED: I had missed the {{ }} around the faculty.name in the div id's and I also hadn't wrapped the jQuery script in a $(document).ready() or included the jQuery cdn. It should work as intended now.
UPDATED 2: Changed the id of elements to use the faculty.pk which should be a number and avoid any issues with spaces.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
$('.btnClick').on('click', function() {
var faculty_id = $(this).attr('id');
$('#'+faculty_id+'_tab').show().siblings('div').hide();
})
})
</script>
<div class="row">
<div class="col-md-3">
<div class="jumbotron">
<h4>Search courses</h4>
<hr>
<br>
<ul>
{% for faculty in faculties %}
<li class="btnClick" id="fac_{{ faculty.pk }}">{{ faculty.name }}</li>
<ul>
{% for department in faculty.department_set.all %}
<li>{{ department.name }}</li>
<ul>
{% for study in department.study_set.all %}
<li>{{ study.name }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
{% endfor %}
</ul>
</div>
</div>
<div class="col-md-9">
<div class="jumbotron">
<div id="1">
<h3>All courses</h3>
<ul>
{% for course in courses %}
<li>
<a class="first" href={{ course.slug }}>{{ course.name }}</a>
</li>
{% endfor %}
</ul>
</div>
{% for faculty in faculties %}
<div id="fac_{{ faculty.pk }}_tab" style="display:none;">
<h3> {{ faculty.name }} courses</h3>
<ul>
{% for department in faculty.department_set.all %}
{% for study in department.study_set.all %}
{% for course in study.study_set.all %}
<li>
<a class="first" href={{ course.slug }}>{{ course.name }}</a>
<p>chinchin</p>
</li>
{% endfor %}
{% endfor %}
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
</div>
</div>

Related

Flask/Jinja2 render multiple collection

I'm creating a MongoDB web application using pymango, Flask and Jinja2.
In connect with the database and I have three collections, and I can insert new data in the collection but when I render in HTML using Jinja2 I get duplicated rows with same data twice basically. I'm new to python and Jinja.
enter code here
#app.route("/addcar", methods=["GET", "POST"])
def addcar():
if request.method == "POST":
cars = {
"car_image": request.form.get("car_image"),
"car_year": request.form.get("car_year"),
"car_name": request.form.get("car_name"),
"car_design": request.form.get("car_design"),
"car_driver1": request.form.get("car_driver1"),
"car_driver2": request.form.get("car_driver2")
}
specs = {
"spec_engine": request.form.get("spec_engine"),
"car_power": request.form.get("car_power"),
"trasmission": request.form.get("trasmission")
}
stats = {
"races": request.form.get("races"),
"wins": request.form.get("wins"),
"podiums": request.form.get("podiums"),
"poles": request.form.get("poles"),
"fast_laps": request.form.get("fast_laps"),
"constructor_champ": request.form.get("constructor_champ"),
"drivers_champ": request.form.get("drivers_champ"),
"description": request.form.get("description")
}
mongo.db.cars.insert_one(cars)
mongo.db.specs.insert_one(specs)
mongo.db.stats.insert_one(stats)
flash("Car Successfully Added")
return redirect(url_for("get_cars"))
return render_template("addcar.html")`
enter code here
enter code here
{% extends "base.html" %}
{% block content %}
<div class="row row justify-content-center mt-4">
{% for car in cars %}
<div class="card mb-3" style="max-width: 840px;">
<div class="row g-0">
<div class="col-md-4">
<img src="{{ car.car_image }}" class="imgCard" alt="ferrari image">
</div>
<div class="col-md-8">
<div class="card-body">
<ul class="list-group list-group-flush">
<li class="list-group-item"><strong>Year</strong>: {{ car.car_year }}</li>
<li class="list-group-item"><strong>Name</strong>: {{ car.car_name }}</li>
<li class="list-group-item"><strong>Designer</strong>: {{ car.car_design }}</li>
</ul>
{% for spec in specs %}
<ul class="list-group list-group-flush">
<li class="list-group-item"><strong>Engine</strong>: {{ spec.spec_engine }}</li>
<li class="list-group-item"><strong>Power</strong>: {{ spec.car_power }}</li>
<li class="list-group-item"><strong>Trasmission</strong>: {{ spec.trasmission }}</li>
</ul>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
enter code here
{% endblock %}
If your html file looks something like this, it will not show replicated statements.
{% extends "base.html" %}
{% block content %}
<div class="row row justify-content-center mt-4">
<div class="card mb-3" style="max-width: 840px;">
<div class="row g-0">
<div class="col-md-4">
<img src="{{ car['car_image'] }}" class="imgCard" alt="ferrari image">
</div>
<div class="col-md-8">
<div class="card-body">
<ul class="list-group list-group-flush">
<li class="list-group-item"><strong>Year</strong>: {{ car['car_year' }}</li>
<li class="list-group-item"><strong>Name</strong>: {{ car['car_name'] }}</li>
<li class="list-group-item"><strong>Designer</strong>: {{ car['car_design'] }}</li>
</ul>
<ul class="list-group list-group-flush">
<li class="list-group-item"><strong>Engine</strong>: {{ spec['spec_engine'] }}</li>
<li class="list-group-item"><strong>Power</strong>: {{ spec['car_power'] }}</li>
<li class="list-group-item"><strong>Trasmission</strong>: {{ spec['trasmission'] }}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
In your flask views, change the return statement to this,
return render_template("addcar.html", car=cars, spec=specs)
Assuming that the html written above is the

maximum recursion depth exceeded while calling a Python object when creating child page of parent page

This is my child code page
{% if post.page_set.all %}
{% for child in post.page_set.all %}
<div>
<h5>
{{child.title}} <i class="fa fa-plus" style="font-size:15px ;color:#2F4F4F;"></i>
</h5>
{% include "makerobosapp/child_code.html" with post=post %}
</div>
{% endfor %}
{% endif %}
And this is my homepage where i want to show child post title
{% block content %}
{% for post in posts %}
<div class="post-content">
<h3>
{{post.title}} <i class="fa fa-plus" style="font-size:20px ;color:#2F4F4F;"></i>
</h3>
<p>{{post.content| safe |linebreaksbr}}</p>
<div class="date">
<p>published date: {{ post.published_date }}</p>
</div>
{% include "makerobosapp/child_code.html" with post=post %}
{% endfor %}
{% endblock %}
I suspect you wanted to recurse into the child, not the parent:
{% include "makerobosapp/child_code.html" with post=child %}

Sorting Outputs of a List Into Different <UL> Tags Django Template

I have the following code in one of my templates. As you can see, there is a lot of repetition going on. Hence, I am wondering if I can somehow use Django Template to consolidate this code while achieving the same (or closely comparable) result when it comes to HTML. Namely, I am interested if I can sort the todo entries into two different <ul> tags on the page, depending on the boolean value of todo.todo_completed.
{% block content %}
{% if todo_list %}
<ul class="list-group">
{% for todo in todo_list %}
{% if not todo.todo_completed %}
<li class="list-group-item">
<div class="row">
<div class="col-sm-5">
<a href="{% url 'list:todo-detail' todo.id %}" >{{ todo.todo_name }}</a>
</div>
<div class="col-sm-6">
</div>
<div class="col-sm-1">
{% bootstrap_icon "ok" %}
{% bootstrap_icon "remove-circle" %}
</div>
</div>
</li>
{% endif %}
{% endfor %}
</ul>
<ul class="list-group">
{% for todo in todo_list %}
{% if todo.todo_completed %}
<li class="list-group-item">
<div class="row">
<div class="col-sm-5">
{{ todo.todo_name }}
</div>
<div class="col-sm-6">
</div>
<div class="col-sm-1">
{% bootstrap_icon "ok" %}
{% bootstrap_icon "remove-circle" %}
</div>
</div>
</li>
{% endif %}
{% endfor %}
</ul>

Is this how to check if an object has no related objects in templates?

This is what I currently has to check if the author has some photos in the related photo model:
{% if author.photo_set.count > 0 %}
<h2>...</h2>
<div style="clear: both;"></div>
<div class="author_pic">
{% for photo in author.photo_set.all %}
<img src="..." />
{% endfor %}
<div style="clear: both;"></div>
</div>
<div style="clear: both;"></div>
{% endif %}
Is this the right way or I can avoid having two queries somehow?
Thanks.
You can use the with tag to avoid multiple queries.
{% with author.photo_set.all as photos %}
{% if photos %}
<h2>...</h2>
<div style="clear: both;"></div>
<div class="author_pic">
{% for photo in photos %}
<img src="..." />
{% endfor %}
<div style="clear: both;"></div>
</div>
<div style="clear: both;"></div>
{% endif %}
{% endwith %}
There is also the empty tag that you can use within a for loop, but that probably doesn't apply to your example.
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#for-empty
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athlete in this list!</li>
{% endfor %}
<ul>
AS #pyrospade suggsted, you can look if the photos object exists. Or you could also check the length (check the length template tag) of the list of photo_set as follows:
{% if author.photo_set.all|length > 0 %}
<h2>...</h2>
<div style="clear: both;"></div>
<div class="author_pic">
{% for photo in author.photo_set.all %}
<img src="..." />
{% endfor %}
<div style="clear: both;"></div>
</div>
<div style="clear: both;"></div>
{% endif %}

Checking if authenticated in Django template inheritance

I have the following code in a template and am having difficulty showing when a user is logged in. I will be able to login, but when I revisit the page, it shows that I'm still not authenticated.
{% extends "base.html" %}
{% load catalog_tags %}
{% block site_wrapper %}
<div id = "main">
Skip to main content
<div id = "banner">
<div class="bannerIEPadder">
<div class="cart_box">
{% cart_box request %}
</div>
</div>
</div>
<div style="float:right;">[search box goes here]</div>
<div id="navigation">
<div class="navIEPadder">
<!--navigation tabs at the top of each page -->
{% comment %}{% include "tags/navigation.html" %} {% endcomment %}
{% category_list request.path %}
</div>
</div>
<div id="middle">
<div id="sidebar">
<!--<div class="sidebarIEPadder">[search box goes here]</br>
{% comment %}{% category_list request.path %}{% endcomment %}
</div>-->
</div>
<div id="content">
<!-- <a name = "content"></a>-->
<div class="contentIEPadder">
{% block content %}{% endblock %}
</div>
</div>
</div>
<div id="footer">
<div class="footerIEPadder">
{% footer_links %}
</div>
</div>
</div>
{% endblock %}
And here's the file it references. Since this will be an extension of all templates, is there something I need to consider?
###category_list.html
<!--<h3>Categories</h3>-->
<!--<ul id="categories">-->
<ul>
{% with active_categories as cats %}
{% for c in cats %}
<li>
{% comment %}
{% ifequal c.get_absolute_url request_path %}
{{c.name}}
{% else %}
{% endcomment %}
<div>{{c.name}}</div>
{% comment %}{% endifequal %}{% endcomment %}
</li>
{% endfor %}
<div class="fr">
<ul>
<li>
{% if user.is_authenticated %}
Logout
{% else %}
Login
{% endif %}
</li>
</div>
{% endwith %}
</ul>
<div class="cb"></div>
Am I missing something here?
You need to pass a RequestContext to the template. The easiest way to do this is to import django.shortcuts and use the render method in your view:
return render(request, "my_template.html")
Is django.contrib.auth.context_processors.auth in your TEMPLATE_CONTEXT_PROCESSORS setting.py?
Do you use requestContext rendering template?
Check that sessions are enabled: MIDDLEWARE_CLASSES should contains 'django.contrib.sessions.middleware.SessionMiddleware'

Categories

Resources