I have in python a dictionary that represents a tree style parent child relationship. I want to display the dictionary on the webpage. FYI: The dictionary will end up being all names and will very base on the person entering info.
Example dictionary from Python:
dict_ = {'A':['B', 'C'], 'B':['D','E'], 'C':['F', 'G', 'H'], 'E':['I', 'J']}
root = 'A'
The desired HTML output display would be.
A
├── B
│ ├── D
│ └── E
│ ├── I
│ └── J
└── C
├── F
├── G
└── H
I not sure how to get this type of display using flask, Jinja, of other options like javascript. Some guidance, partial, or full answers would be great. ( I did learn how to use treelib to display it in terminal but not html.)
In my solution, a helper function is used to create a tree consisting of dicts from the given dict with the lists it contains. Thus, the hierarchy is given to render a structure of nested list elements with a jinja macro.
def tree_find(e, t):
if e in t:
return t
for v in t.values():
r = tree_find(e, v)
if r:
return r
return None
#app.route('/')
def index():
dict_ = {'A':['B', 'C'], 'B':['D','E'], 'C':['F', 'G', 'H'], 'E':['I', 'J']}
tree = {}
for k,v in dict_.items():
n = tree_find(k, tree)
(tree if not n else n)[k] = {e:{} for e in v}
return render_template('index.html', **locals())
{% macro render_tree(d) -%}
<ul>
{% for k,v in d.items(): -%}
<li><span>{{k}}</span>
{% if v -%}
{{ render_tree(v) }}
{% endif -%}
</li>
{% endfor -%}
</ul>
{%- endmacro %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tree</title>
<style type="text/css">
ul, li {
position: relative;
}
ul {
list-style: none;
padding-left: 16px;
}
li::before, li::after {
content: "";
position: absolute;
left: -12px;
}
li::before {
border-top: 1px solid #000;
top: 9px;
width: 8px;
height: 0;
}
li::after {
border-left: 1px solid #000;
height: 100%;
width: 0px;
top: 2px;
}
ul > li:last-child::after {
height: 8px;
}
</style>
</head>
<body>
{{ render_tree(tree) }}
</body>
</html>
Related
I'm looking to use a drag-n-drop feature for updating a table in my Django model.
I need to be able to drag items (a list of model objects) between 3 baskets and update the item's basket type in the model. My model contains food items and the status of these items. So the food.names will be the items dragged and 3 baskets are the food.status: 'don't have', 'have', 'need to buy'. Just like this example: https://www.javascripttutorial.net/sample/webapis/drag-n-drop-basics/.
<!DOCTYPE html>
<html lang="en">
<head>
<style>
#div1, #div2, #div3 {
float: left;
width: 100px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
</style>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>
<h2>Drag and Drop</h2>
<p>Drag the items back and forth between the three div elements.</p>
{% for row in all_food %}
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
{% if row.status_type == 'have'%}
<ul>
<li>{{row}}
</ul>
{% endif %}
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="div3" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
{% endfor %}
</body>
</html>
The code above comes out as 33 boxes with the items in the for loop scattered among the boxes.
I mainly use Python and don't have much experience working with front end code. What can I try next?
I am trying to use django form to insert some information into the database, but the insert is now working properly.
This is for form page with some inputs that I am using.
<!DOCTYPE html> <html lang="en">
<head>
<!-- /Css -->
<link rel = "stylesheet" type = "text/css" href = "../static/survey.css" />
<!-- /Css -->
<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>Preencha a pesquisa de satisfação</title>
<style>
* {
box-sizing: border-box;
}
input[type=submit] {
background-color: #4CAF50;
color: white;
padding: 10px 10px;
border: none;
border-radius: 4px;
cursor: pointer;
float: right;
}
input[type=submit]:hover {
background-color: #45a049;
}
.col-25 {
float: left;
width: 50%;
margin-top: 6px;
}
.col-75 {
float: left;
width: 100%;
margin-top: 5px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
</style>
<!-- /Fonts -->
<link href='https://fonts.googleapis.com/css?family=Comfortaa' rel='stylesheet'> <link href="https://fonts.googleapis.com/css?family=Poppins:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900" rel="stylesheet">
<!-- /Fonts -->
</head>
<body>
<h2>Pesquisa de satisfação</h2>
<p>Avalie a sua experiência em nosso restaurante e nos ajude a melhor o atendimento.</p>
<div class="container">
<h2>{{ note }}</h2>
<form class="formSurvey" action="{% url 'servicesurvey' %}" method="post">
{% csrf_token %}
{{ surveyform }}
<div class="row">
<input type="submit" value="Submit">
</div>
</form>
</div>
<div>
Voltar
</div>
</body> </html>
view.py with the function servicesurvey that calls the POST method and return the render.
from django.shortcuts import render
from .forms import SurveyForm
from .models import Survey
def home(request):
return render(request, 'survey/home.html')
def servicesurvey(request):
if request.method == 'POST':
filled_form = SurveyForm(request.POST)
if filled_form.is_valid():
note = 'Obrigado por responder nossa pesquisa'
new_form = SurveyForm()
return render(request, 'survey/servicesurvey.html', {'surveyform': new_form, 'note':note})
else:
form = SurveyForm()
return render(request, 'survey/servicesurvey.html', {'surveyform':form})
def qrcode(request):
return render(request, 'survey/qrcode.html')
models.py with the 2 inputs that I am trying to save at my database.
from django.db import models
class Survey(models.Model):
aboutTheService = models.CharField(max_length=100)
aboutTheFood = models.CharField(max_length=100)
I am learning web development using django framework. I have little trouble in running python code in an html page. I need to iterate through a list of strings which basically contains the paths of images that I want to show in a carousel. I am getting this error "Invalid block tag on line 83: 'with.i', expected 'endblock'. Did you forget to register or load this tag?" in galleryPage.html file when I try to open that page. These are the few lines of code that I've written so far
/views.py/
def galleryPage(request):
from os import listdir
from os.path import isfile, join
ImageList = []
imagePath = "static/images/gallery/"
for f in listdir(imagePath):
temp = join(imagePath, f)
if isfile(temp):
temp = "../" + temp
ImageList.append(temp)
return render(request, "galleryPage.html", {"imageList": ImageList})
/galleryPage.html/
{% extends 'base.html' %}
{% block title %} GALLERY {% endblock %}
{% block slideshow %}
* {box-sizing: border-box;}
body {font-family: Verdana, sans-serif;}
.mySlides {display: none;}
img {vertical-align: middle;}
/* Slideshow container */
.slideshow-container {
max-width: 1000px;
position: relative;
margin: auto;
}
/* Caption text */
.text {
color: #f2f2f2;
font-size: 15px;
padding: 8px 12px;
position: absolute;
bottom: 8px;
width: 100%;
text-align: center;
}
/* Number text (1/3 etc) */
.numbertext {
color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
top: 0;
}
/* The dots/bullets/indicators */
.dot {
height: 15px;
width: 15px;
margin: 0 2px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
}
.active {
background-color: #717171;
}
/* Fading animation */
.fade {
-webkit-animation-name: fade;
-webkit-animation-duration: 1.5s;
animation-name: fade;
animation-duration: 1.5s;
}
#-webkit-keyframes fade {
from {opacity: .4}
to {opacity: 1}
}
#keyframes fade {
from {opacity: .4}
to {opacity: 1}
}
/* On smaller screens, decrease text size */
#media only screen and (max-width: 300px) {
.text {font-size: 11px}
}
{% endblock %}
{% block content %}
<div class="slideshow-container">
{% with.i = 0 %}
<indent>
{{ for image in imageList.0: }}
{% ++i %}
<div class="mySlides fade">
<div class="numbertext"> {% i %} / {{ imageList.size() }} </div>
<img src="{{ image }}" style="width:100%">
<div class="text">Caption Text</div>
</div>
</indent>
{% endwith %}
</div>
<br>
<div style="text-align:center">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
<script>
var slideIndex = 0;
showSlides();
function showSlides() {
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("dot");
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slideIndex++;
if (slideIndex > slides.length) {slideIndex = 1}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
setTimeout(showSlides, 2000); // Change image every 2 seconds
}
</script>
{% endblock %}
{% with.i = 0 %}
should be
{% with i=0 %}
Why do you have imageList.0 instead of imageList?
Also, I think you may want to consider combining your current "with" and "for" into one "for" loop like in the docs I posted above:
{% for key, image in imageList %}
<div class="mySlides fade">
<div class="numbertext"> {% key %} / {{ imageList.size() }} </div>
<img src="{{ image }}" style="width:100%">
<div class="text">Caption Text</div>
</div>
{% endfor %}
This way you won't need to increment i yourself and you take away some complexity (and some sources of errors).
I am using Python 3.52 and I have 2 keys to a single value in a dict:
code:
for key, value in unused_reserved_instances.items():
print("Key: ", key)
print("Value: ", value)
output:
Key: ('m3.large', 'us-west-2b')
Value: 1
Key: ('m3.xlarge', 'us-west-2b')
Value: 1
jinja template:
<!DOCTYPE html>
<html>
<head>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 3px;
text-align: center;
}
table#t01 {
width: 30%;
background-color: #f1f1c1;
}
</style>
</head>
<body>
<table id="t01">
<tr>
<th>Instance Type</th>
<th>Count</th>
</tr>
{% for key, value in unused_reserved_instances.items() %}
<tr>
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
Instead of this:
Instance Type Count
('m3.large', 'us-west-2b') 1
('m3.xlarge', 'us-west-2b') 1
I want it to be something like one of the below examples (just without the quotes and brackets):
Instance Type Count
m3.large, us-west-2b 1
m3.xlarge, us-west-2b 1
Or maybe like this:
Instance Type Count
m3.large - us-west-2b 1
m3.xlarge - us-west-2b 1
Thanks
You can join the strings in the tuple like so:
{% for key, value in unused_reserved_instances.items() %}
<tr>
<td>{{key|join(' - ')}}</td>
<td>{{value}}</td>
</tr>
{% endfor %}
You can iterate over that tuple:
<td>{% for v in key %}{{v}}{%endfor%}</td>
I have two div containers for which I have fixed the height and width. One of the containers holds the body of the blogpost and other holds the list of all the posts created. Since, body of a blogpost or list of posts can be larger than the size of their div container. So, I want to dynamically increase container's size when they exceed its size. How can I achieve it either using css or javascript?
css file
body {
background-color:#FFCCFF;
}
#container {
position:absolute;
top:50px;
left:100px;
right:100px;
bottom:50px;
}
#content {
margin-top:20px;
padding:0;
width:70%;
height:550px;
border:1px solid black;
background-color: #282828 ;
color:white;
}
#footer {
width:100%;
height:50px;
border:1px solid black;
}
#rightnav {
position:absolute;
top:18px;
right:20px;
width:275px;
height:550px;
background-color: #282828 ;
}
#rightnav p {
margin:0px 0 10px 0px;
padding:0px;
color:#CCCCFF;
}
#rightnav h2 {
text-align: center;
background-color: #000000;
margin:0;
color:#FF9900;
}
#rightnav a {
text-decoration: none;
}
#posts {
padding:0;
width:80%;
border:1px solid black;
}
#posts h2 {
margin:0;
padding:0;
}
#posts p {
margin:5px;
padding:0;
}
#content a {
text-decoration: none;
background-color: none;
color:black;
}
base.html #every other html files inherit from this base file
{% load staticfiles %}
<html>
<head>
<link rel="stylesheet" href="{% static 'css/base.css' %}" type="text/css">
</head>
<body>
<div id = "container" style="clear:both;">
<div id = "content">
{% block post %}
{% endblock %}
</div>
<div id = "rightnav">
<h2>Popular Posts</h2>
{% block popular_posts %}
{% endblock %}
</div>
</div>
</body>
</html>
post.html #the template which deals with showing posts
{% extends "blog/base.html" %}
{% block post %}
{% load django_markdown %}
<h2>{{post.title}}</h2>
{{ post.body|markdown }}
{% endblock %}
{% block popular_posts %}
{% for post in posts %}
<p>{{ post.title }}</p>
{% endfor %}
{% endblock %}
Adding to Marcanuy's answer, you have to remove the bottom:50px given to the #container div.
And by removing position:absolute from unwanted places will make your css neat. If you want to position your div side by side, you can use display:flex for your parent (#container) div.
EDIT: Have also removed the position:absolute property and have added margin:50px to make your div center-aligned. (You can also use padding property)
Refer : JsFiddle
#container {
position:absolute;
top:50px;
left:100px;
right:100px;
}
#content {
padding:0;
width:70%;
min-height:550px;
border:1px solid black;
background-color: #282828 ;
color:white;
}
#rightnav {
width:275px;
min-height:550px;
background-color: #282828 ;
}
Change your height with min-height, this will make your containers have at least the specified height, then they will grow and fit their content needs.
#rightnav {
min-height:550px;
}
#content {
min-height:550px;
}