flask include template with variable - templates

Just curious why this is working, since haven't found such examples in flask and jinjia2 official docs. It seems include is just simply put the content to the place just as it is, right?
# app.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
names = ['John', 'James', 'Jenny']
return render_template('index.html', names=names)
if __name__ == '__main__':
app.run(port=5200)
<!-- index.html -->
<!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">
<title>Home</title>
</head>
<body>
Welcome!
<!-- I know this is working as official docs -->
{% for name in names %}
<div class='card'>Welcome {{ name }}!</div>
{% endfor %}
<!-- but haven't found any examples like below, but it works -->
{% for name in names %}
{% include "card.html" %}
{% endfor %}
</body>
</html>
<!-- card.html -->
<div class='card'>Welcome {{ name }}!</div>
code example in vscode

From https://jinja.palletsprojects.com/en/3.0.x/templates/
Include
The include tag is useful to include a template and return the
rendered contents of that file into the current namespace:
{% include 'header.html' %}
Body {% include 'footer.html' %}
Included templates have access to the variables of the active context
by default.

This code will work because cards.html will be reloaded at each step of the "for" loop.
We can include a template in another template in the jinja structure. We don't have to use "for" when doing this.
The list elements to be navigated in the "for" loop are rendered from the flask view. In this way, we can use the rendered list and its elements as we want in the specified template while rendering.
{% for name in names %}
{% include "card.html" %}
{% endfor %}

Related

Can't figure out what did I miss here, it says 'list' is not a valid function. Any help would be appreciated

The error that occurs during template rendering:
In template /Users/mac/myfirstproject/templates/base_layout.html, error at line 12
Reverse for 'list' not found. 'list' is not a valid view function or pattern name.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ARTICLES</title>
<link rel="stylesheet" href="{% static 'styles.css' %}">
</head>
<body>
<div class="wrapper">
<h1><img src="{% static 'logo.png' %} "/></h1>
{% block content %}
{% endblock %}
</div>>
</body>
</html>
As indicated in Andrei's comment above, you need to make sure you have 'list' set up as a valid url name in your urls.py file.
something like this:
urls.py
from django.conf.urls import url
from .views import list_view
urlpatterns = (
url(r'^list$', list_view, name='list'),
)
in order to use the {% url 'url_name' %} template tag, you have to have a url named url_name, and if you have your project divided into apps, the format is:
`{% url 'app_name:url_name' %}. If you post your urls.py file, perhaps we can be more helpful.

Django - name 'title' is not defined

An hour ago I started to make a web application, with Django. I watched this video https://www.youtube.com/watch?v=qDwdMDQ8oX4
I'm following all his steps, but after changing some stuff, I've got an error which says
title is not defined in /about/.
Here's my code for the route /about/. The code is equal to my other home page, but this one doesn't work.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
{% if title %}
<title>Django BLog - {{ title }}</title>
{% else %}
<title>Django blog</title>
{% endif %}
</head>
<body>
</body>
</html>
As shown in the traceback, title is not defined in your view. This happens because title is not wrapped in quotes so it assumes it's a variable.
Add the quotation marks like so 'title' and you should be fine.
So, you should change line 29 in views.py to
return render(request, 'blog/about.html', {'title': 'About'})

Django render_to_response displaying raw text

I am new to Django and I'm trying to create a simple html skeleton to verify everything is working properly. Everything is working (server is running and it loads the file) yet when I put in HTML code it is displayed as raw text instead of rendering it correctly.
My views.py is as follows
def home(request):
return render_to_response('index.html')
My 'index.html' is as follows
<!DOCTYPE html >
<html>
  <head>
   <meta charset="UTF-8">
   <title> awesome </title>
  </head>
  <body>
  
  </body>
</html>
What should I do to have it render correctly? (Display only "awesome")
EDIT
As far as this problem goes, the error came in that I saved the raw code as html. When I chose this option, it added the code to make html render it look like a raw input.
Moral of the story: Make sure you do your edits in a text editor and change extension by hand
A few problems..
1: what's with the spaces inside your tags?
< title > is invalid. It needs to be <title>Foo</title> That's why you're seeing "html".
2: Even if the title tag was written correctly, a title tag does not render, so you will get a blank page. If you want to display "awesome" -- you need to write it inside the body tag.
<body>awesome</body>
1) Remove spaces in < title > tag
2) And add bellow code in your urls.py file no need to map with view you can render html page from url also
(r'^home/$', 'django.views.generic.simple.direct_to_template',
{'template': 'index.html'}),
The first thing you need to do is create a "base" template so the other templates can extend from. You will normally call it base.html but you can use the name you want. You also need to create blocks that extended templates can use:
base.html
<!DOCTYPE html >
<html>
<head>
<meta charset="UTF-8">
< title > awesome < /title >
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
Then, you have to extend base.html from your index.html and use the content block we have created:
index.html
{% extends "base.html" %}
{% block content %}
{% endblock %}
At this point, index.html will be exactly as base.html because you are not showing anything inside the content block. Update your view with some data like this:
views.py
def home(request):
data = {'name': 'YourName', 'age': 25}
return render_to_response('index.html', data)
Now, again, update your index.html:
index.html
{% extends "base.html"%}
{% block content %}
<p>My name is {{ name }}</p>
<p>I'm {{ age }} years old</p>
{% endblock %}
Don't forget to read the fine tutorial.

django static files

I have in my urls.py line:
if settings.DEBUG==True:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_DOC_ROOT})
)
In my settings file something like this:
STATIC_DOC_ROOT = os.path.join(os.path.dirname(__file__),'static').replace('\\','/')
And when I go to / in my page everything work just great. And when I click a link from / to anther page I don't have CSS applied because of 404 error. He tries to load a CSS file from that URL.
http://localhost:8000/show/sth/static/style.css
Here is my urls.py for this method
(r'^show/(?P<subject>[^/]+)/(?P<title>[^/]+)$','show'),
I have url /links and css works just in this one template it does not work. It seems that these parameters messing something up. Any suggestions why this fails?
Here is my template code:
{% extends "szkielet.html" %}
{% block tresc %}
<div id="content">
<div class="post">
<h2 class="title">{{ notatka.tytul }}</h2>
<p class="meta"><span class="author">{{ notatka.user.name }}</span> <span class="date">July 07, 2010</span> <span class="links">Comments</span></p>
<div class="entry">
<p>{{ notatka.tresc }}</p>
</div>
</div>
</div>
{% endblock %}
Szkielet.html - it is my base
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Perfect Blemish by Free CSS Templates</title>
<link href="{{ MEDIA_URL }}style.css" rel="stylesheet" type="text/css" media="screen" />
</head>
<body>
Here is part responsible for CSS it is only one style sheet .
URL's could potentially be set to override the static url path but that's not the case here! So your URL conf doesn't have anything to do with this.
The core problem is that your template is rendering an incorrect URL: http://localhost:8000/show/sth/static/style.css should be http://localhost:8000/static/style.css correct?
Show us your template since that seems to be the problem. Sounds to me like you just have a relative URL set for your CSS instead of absolute or /static/style.css
What is your {{ media_url }}? It's supposed to be absolute, and begin with a /

How do I retain the whitespace in templates' blocks?

I'm using SHPAML (HAML for python) for Django, however, I'm facing problems converting SHPAML -> HTML because of whitespace issues when overriding some blocks, heres an example:
In skeleton.shpaml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{{ title }}</title>
{% comment %}
<link rel="shortcut icon" href="/static/images/favicon.ico" type="image/x-icon"/>
{% endcomment %}
{% if css_list %}
{% for css in css_list %}
<link type="text/css" rel="stylesheet" href="{{css_relative}}{{ css }}">
{% endfor %}
{% endif %}
{% if js_list %}
{% for js in js_list %}
<script type="text/javascript" src="{{js_relative}}{{ js }}">
</script>
{% endfor %}
{% endif %}
{% if no_cache %}
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
{% endif %}
</head>
body
#nonFooter
#content
{% block header %} {% endblock %}
#maincontent
{% block content %} {% endblock %}
#footer
</html>
In index.shpaml:
{% extends "includes/skeleton.shpaml" %}
{% block content %}
asd
.test
.test2 | meh
{% endblock %}
In the end, my output is this:
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Home | Zineified</title>
<link type="text/css" rel="stylesheet" href="/media/css/base.css">
<script type="text/javascript" src="/media/js/jquery-1.3.2.min.js">
</script>
<script type="text/javascript" src="/media/js/jquery.form.js">
</script>
<script type="text/javascript" src="/media/js/base.js">
</script>
</head>
body
#nonFooter
#content
#maincontent
asd
.test
.test2 | meh
#footer
</html>
As you can see, whitespace is not preserved in the blocks. The next line in index.shpaml goes straight down into the next line in skeleton.shpaml. How can I prevent this and retain whitespace through template extending?
It looks like the SHPAML preprocessor is not getting invoked BEFORE Django. What I typically do is write all my documents in SHPAML with a .shpaml extension, and then I convert them to Django with the .html extension, and then let Django do its magic. So you will want statements like "extends" and "include" to refer to the .html document that has already been preprocessed.
Your base shpaml doc will look something like this:
html
body
#main_page
{% block body %}
{% endblock %}
And then the document that extends it will look something like this:
{% extends 'base.html' %}
{% block body %}
p
This is a paragraph about {{ book }}...
{% endblock %}
And then you want to preprocess them BEFORE Django sees them. I usually preprocess them with a Python script right before doing "manage.py runserver."
from docs:
spaceless
Removes whitespace between HTML tags. This includes tab characters and newlines.
Example usage:
{% spaceless %}
<p>
Foo
</p>
{% endspaceless %}
This example would return this HTML:
<p>Foo</p>
Only space between tags is removed -- not space between tags and text.
You can also remove excess spaces/newlines manually, but that will reduce the readability of the template.
#maincontent
asd
You mean misalignment here? Well, align your index.shpaml accordingly:
{% extends "includes/skeleton.shpaml" %}
{% block content %}
asd
.test
.test2 | meh
{% endblock %}
I've wrote a simple script to recursively explore a directory and find all shpaml files and convert them to *.htm. Thought I'd share it:
#!/usr/bin/env python
#===============================================================================
# Recursively explore this entire directory,
# and convert all *.shpaml files to *.htm files.
#===============================================================================
import shpaml
import os, glob
count = 0
def main():
global count
cwd = os.path.dirname(os.path.abspath(__file__))
convert_and_iterate(cwd)
print("Done. Converted "+str(count)+" SHPAML files.")
def convert_and_iterate(path):
global count
for file in glob.glob(os.path.join(path,'*.shpaml')):
#getting generic name
file_basename = os.path.basename(file)
gen_name = os.path.splitext(file_basename)[0]
#opening shpaml file and converting to html
shpaml_file = open(file)
shpaml_content = shpaml_file.read()
html_content = shpaml.convert_text(shpaml_content)
#writing to *.htm
html_file = open(os.path.join(path,gen_name+".htm"),"w")
html_file.write(html_content)
#incrementing count
count += 1
#transverse into deeper directories
dir_list = os.listdir(path)
for possible_dir in dir_list:
if os.path.isdir(os.path.join(path,possible_dir)):
convert_and_iterate(os.path.join(path,possible_dir))
if __name__ == "__main__":
main()