Creating HTML in python
Asked Answered
A

8

64

I am looking for a way to create html files dynamically in python. I am writing a gallery script, which iterates over directories, collecting file meta data. I intended to then use this data to automatically create a picture gallery, based on html. Something very simple, just a table of pictures.

I really don't think writing to a file manually is the best method, and the code may be very long. So is there a better way to do this, possibly html specific?

Anticipative answered 20/2, 2010 at 5:18 Comment(0)
S
17

I think, if i understand you correctly, you can see here, "Templating in Python".

Shanonshanta answered 20/2, 2010 at 5:22 Comment(0)
I
90

Dominate is a Python library for creating HTML documents and fragments directly in code without using templating. You could create a simple image gallery with something like this:

import glob
from dominate import document
from dominate.tags import *

photos = glob.glob('photos/*.jpg')

with document(title='Photos') as doc:
    h1('Photos')
    for path in photos:
        div(img(src=path), _class='photo')


with open('gallery.html', 'w') as f:
    f.write(doc.render())

Output:

<!DOCTYPE html>
<html>
  <head>
    <title>Photos</title>
  </head>
  <body>
    <h1>Photos</h1>
    <div class="photo">
      <img src="photos/IMG_5115.jpg">
    </div>
    <div class="photo">
      <img src="photos/IMG_5117.jpg">
    </div>
  </body>
</html>

Disclaimer: I am the author of dominate

Imposture answered 29/5, 2014 at 5:2 Comment(3)
Best thing since sliced bread. I have dabbled with the same ideas for 20 years, with false starts in C, Lisp and IIRC (shudder) PHP but my half-baked solutions were always even more painful than just sprinkling HTML between code (PHP) or print-ing HTML. The Dominate library just clicks for me. To me Dominate feels very lisp-y in the sense that you always hear that Lisp is great for using the language itself as a Domain Specific Language. Well, it turns out Python is really good for this as well!Fleecy
Agreed! This is truly awsomeKurth
Well done, @Knio. Your library is still holding up after more than a decade. This is exactly what I needed.Smetana
S
17

I think, if i understand you correctly, you can see here, "Templating in Python".

Shanonshanta answered 20/2, 2010 at 5:22 Comment(0)
D
15

Use a templating engine such as Genshi or Jinja2.

Dipsomaniac answered 20/2, 2010 at 5:21 Comment(0)
R
10

Python is a batteries included language. So why not use xml.dom.minidom?

from typing import List
from xml.dom.minidom import getDOMImplementation, Document


def getDOM() -> Document:
    impl = getDOMImplementation()
    dt = impl.createDocumentType(
        "html",
        "-//W3C//DTD XHTML 1.0 Strict//EN",
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd",
    )
    return impl.createDocument("http://www.w3.org/1999/xhtml", "html", dt)


def ul(items: List[str]) -> str:
    dom = getDOM()
    html = dom.documentElement
    ul = dom.createElement("ul")
    for item in items:
        li = dom.createElement("li")
        li.appendChild(dom.createTextNode(item))
        ul.appendChild(li)
    html.appendChild(ul)
    return dom.toxml()


if __name__ == "__main__":
    print(ul(["first item", "second item", "third item"]))

outputs:

<?xml version="1.0" ?>
<!DOCTYPE html  PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
<html>
    <ul>
        <li>first item</li>
        <li>second item</li>
        <li>third item</li>
    </ul>
</html>

The interface does not look like pythonic, but if you have been a fronted developer and used JavaScript DOM manipulation, it matches your mind better and yes it frees you from adding a needless dependency.

Reinert answered 26/4, 2020 at 7:26 Comment(1)
Very nice and simple example. ThanksHairless
L
2

Templating, as suggested in other answers, is probably the best answer (I wrote an early, quirky templating module called yaptu, but modern mature ones as suggested in other answers will probably make you happier;-).

However, though it's been a long time since I last used it, I fondly recall the Quixote approach, which is roughly a "reverse templating" (embedding HTML generation within Python, rather than viceversa as normal templating does). Maybe you should take a look and see if you like it better;-).

Literary answered 20/2, 2010 at 14:18 Comment(1)
I clicked around a little and it seems Quixote is still around. A description of for instance the button generator is here: quixote.ca/doc/widgets.txt . All in all, it seems like you can put the Dominate library and Quixote in the same general category. But Quixote seems to do a lot of other things too, server related things. I like your term "reverse templating" - I will start using it to describe the general technique!Fleecy
R
1

Just write a file that contains html

a = '''
<html>
<head>
<h1> hello </h1>
</head>
</html>
  
'''
f = open("myhtmlfile.html", "a")
f.write(a)
Romanic answered 12/1, 2023 at 13:16 Comment(0)
R
0

An alternative to Dominate is Chope, which also supports CSS.

Here's an example:

from chope import *
from chope.css import *

page = html[
    head[
        style[
            Css[
                'body': dict(
                    background_color='linen',
                    font_size=pt/12
                ),
                '.inner-div': dict(
                    color='maroon',
                    margin_left=px/40
                )
            ]
        ]
    ],
    body[
        h1['Title'],
        div(class_='outer-div')[
            div(class_='inner-div')[
                'Some content.'
            ]
        ]
    ]
]

Which will give you

<html>
  <head>
    <style>
      body {
        background-color: linen;
        font-size: 12pt;
      }
      
      .inner-div {
        color: maroon;
        margin-left: 40px;
      }
    </style>
  </head>
  <body>
    <h1>
      Title
    </h1>
    <div class="outer-div">
      <div class="inner-div">
        Some content.
      </div>
    </div>
  </body>
</html>

Disclaimer: I am the creator of Chope

Revival answered 16/4, 2023 at 16:31 Comment(0)
A
0

Using ElementTree

You can also use the standard library:

from xml.etree import ElementTree as ET
resHTML = ET.Element('html',attrib={'lang':'en'})
body = ET.SubElement(resHTML,'body')
p1 = ET.SubElement(body,'p')
span1 = ET.SubElement(p1,'span', attrib={'id': 'anIDA'})
span1.text = "mytext"

with open("HTMLtest.html","wb") as o:
    o.write(b"<!DOCTYPE html>\n")
    o.write(ET.tostring(resHTML))

# cleanest  way using Beautiful Soup
import bs4
with open("HTMLtest.html","w") as o:
    o.write(bs4.BeautifulSoup(ET.tostring(resHTML), "html").prettify())
Adorno answered 26/2 at 15:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.