Python HTML Generator using Yattag Part 1
Python
HTML Generator
Download and install
yattag
pip install yattag
You can download the archive here:
python setup.py install or: python3 setup.py install
Yattag is a Python library for
generating HTML or XML in a pythonic way. With
Yattag,
·
you
don't have to worry about closing HTML tags
·
your
HTML templates are Python code. Not a weird template language. Just
Python.
·
you
can easily render HTML forms, with defaults values and error messages.
It's actually easier and more readable to
generate dynamic HTML with Yattag than to write static HTML.
1. Tags and text
from yattag import Doc
doc,tag,text=Doc().tagtext()
with tag('h1'):
text('Hello
World!')
print(doc.getvalue())
How this works
Have you ever used a
list of strings and used the join method to produce just one
big string?
I mean, just like this:
mylist = []
mylist.append('Everybody')
mylist.append('like')
mylist.append('pandas.')
mystring = ' '.join(mylist) # mystring
contains "Everybody like pandas."
Well, the yattag.Doc class
works just like that. It has more functionalities than just appending a string,
but the idea is the same? That's what makes it so fast.
I create a Doc instance.
I use its methods to append content to it (for example, the text method
appends some text, the tag method appends a html tag etc...).
When I'm done, the getvalue method returns the whole content
as a big string. Exactly like the join method in our example
with a list.
Let's get back to our
list example. To avoid typing too much, and also to avoid an attribute lookup
each time we call the append method, we could use this little
trick:
mylist = []
append = mylist.append
append('Everybody')
append('like')
append('pandas.')
mystring = ' '.join(mylist)
Similarly, the tag and text methods
are used very often with Yattag. So, your code is a lot more concise if,
instead of writing mydocument.tag, you just write tag.
It's also faster: you avoid an attribute lookup each time. That's where
the tagtext method comes into play.
The tagtext method
is a helper method that returns a triplet composed of:
·
the Doc instance
itself
·
the tag method
of the Doc instance
·
the text method
of the Doc instance
It's just a little trick
to make html templates more concise and beautiful.
The "doc, tag,
text = Doc().tagtext()" line is thus equivalent to the longer code:
doc = Doc()
tag = doc.tag
text = doc.text
The tag method
The tag method
returns a context manager. In Python, a context manager is an object that you
can use in a with statement. Context managers have __enter__ and __exit__ methods.
The __enter__ method is called at the beginning of the with block
and the __exit__ method is called when leaving the block.
Now I think you can see
why this is useful for generating xml or html.
with tag('h1') creates a <h1> tag.
It will be closed at the
end of the with block.
This way you don't have
to worry about closing your tags.
Isn't it awesome? The
python interpreter will close all your tags for you. No more headache looking
for unclosed tags.
The tag method
will accept any string as a tag name. So you're not limited to valid HTML tag
names. You can write very strange XML documents if you want. You can specify
tag attributes as keyword arguments.
with tag('icecream',id='2',flavour='vanilla'):
text("This is really delicious.")
Since class is
a reserved keyword of the Python language, we had to replace it with klass.
A klass attribute will be replaced with a class attribute in the end result.
with tag('h2', klass='breaking-news'):
text('India defeats Australia')
In this example we get
the result:
<h2 class="breaking-news"> India defeats Australia </h2>
For any other situation
where an attribute's name can't be expressed as a Python identifier, you can
use (key, value) pairs. For example, HTML5 allows attributes starting with
"data-". In that situation you would do:
with tag('td', ('data-search','bca'), ('data-order','1234'),
id='16' ):
text('Piyush Patel')
You'd get:
<td data-search="bca" data-order="1234" id="16">Piyush
Patel</td>
Note: attributes values are escaped, that is,
the &, < and " characters are replaced with &,<, and
". For attributes without a value, just pass a string to the tag method.
For example,
with tag('html','ng-app'):
with tag('body'):
text('Welcome to my AngularJS
application.')
You'll get:
<html ng-app><body>Welcome to my
AngularJS application</body></html>
The text method
We use the text method
to write some text in our document.
The text method
takes a string, escapes it so that it is safe to use in a html document (&,
<, > are replaced with &,< and >) and appends the
escaped string to the document.
Actually, you can pass
any number of strings to the text method. For example:
text('Hello ', username, '!')
If you don't want your
strings to be escaped, see the asis method in the next
section.
2. Appending strings "as is"
from yattag import Doc
doc,tag,text=Doc().tagtext()
doc.asis('<!DOCTYPE html>')
with tag('html'):
with tag('body'):
text('Hello World!')
print(doc.getvalue())
The asis method
appends a string to the document without any form of escaping.
In this example, we
don't want the < and > characters of
the '<!DOCTYPE html>' string to be replaced with < and >.
We really want the < and > characters
to be added as is. So we use the asis method instead of
the text method.
Our little example
prints
<!DOCTYPE html>
<html>
<body>
Hello World!
</body>
</html>
As with the text method,
the asis method can actually take any number of strings as
arguments.
3. Self closing tags
from yattag import Doc
doc,tag,text=Doc().tagtext()
with tag('div', id='photo-container'):
doc.stag('img',src='/myphoto.jpg', klass="photo")
print(doc.getvalue())
The stag method
produces a self closing tag.
As with the tag method,
tag attributes are passed as keyword arguments to the stag method,
and attribute values are escaped (that is, any occurence of the "
character is replaced with ").
In this example we get
the result:
<div id="photo-container">
<img src="/myphoto.jpg" class="photo" />
</div>
Note the / at the end of the self closingimg tag.
4. Setting tag attributes after opening a tag
from yattag import Doc
from datetime import date
today=date.today()
doc,tag,text=Doc().tagtext()
with tag('html'):
with tag('body'):
if today.month==1 and today.day==1:
doc.attr(klass="new-year-style")
else:
doc.attr(klass="normal-style")
text("Welcome to our site")
print(doc.getvalue())
The attr method
sets the value(s) of one or more attributes of the current tag.
As with the tag and stag methods,
tag attributes are passed as keyword arguments.
In our little, example:
January the first, we
get the string: "<html><body class="new-year-style">Welcome to
our site</body></html>".
On other days, we
get "<html><body class="normal-style">Welcome to
our site</body></html>".
Example:
from yattag import Doc
doc,tag,text=Doc().tagtext()
doc.asis('<!DOCTYPE html>')
with tag('html'):
with tag('body'):
with tag('h1'):
text('Hello World!')
with tag('div', id='photo-container'):
doc.stag('img',src='/myphoto.jpg', klass="photo")
with tag('p'):
text('Piyush Patel')
print(doc.getvalue())
Output:
<!DOCTYPE html><html><body><h1>Hello World!</h1><div id="photo-container"><img src="/myphoto.jpg" class="photo" /></div><p>Piyush Patel</p></body></html>
Comments
Post a Comment