Before looking at how to build a static website using Python, we will look at exactly what a static site is and what the advantages are.
And, since there are already a number of free static site generators, why would you want to write your own?
A static website simply consists of a collection of HTML files on a webserver. When you access a particular URL, the server just sends the file to your browser, as is, unchanged.
PythonInformer is a static website. When you access this page:
our webserver simply sends you the file:
Our webserver has an html file for every single article on the site. It also has an html file for all the special pages, such as the recent articles page. There is also a separate page for each tag and category, listing links to the pages that are tagged or categorised with that string.
Of course, that doesn't mean all those html files are maintained manually - that would be madness! Instead all the article pages are written as ordinary text files in a simple format called markdown. Our custom static site generator combines these files with an html template to create the html files automatically. It also creates the special pages, including the tag and category pages, by collating information from the markdown files:
A dynamic website is one where the html is created dynamically each time a page is accessed. It typically stores the main information in a database. When a page is accessed, it reads data from the database, and combines it with an html template to create the page.
You can use an existing content management system (CMS), of which there are many, including Wordpress, Drupal, Joomla, or Django (the most popular Python based system). Or you can roll your own using various frameworks
This is very useful in some cases. For example, if you have a retail website, each time a user looks at a product you can be sure that they are seeing the current price, and how many of that item are in stock. Since the page is created separately for each user, you can also use their buying history to suggest alternatives, additional purchases, or special offers that might interest them.
However, for a blog or an information site, such as PythonInformer, there are few advantages to using a dynamic system, because you will be showing every user the exact same page. Dynamic systems can be quite heavy - you need to worry about security, backups, updates, etc. Adding even simple features to your site often means using a third party plugin - what if it has bugs, or the person who wrote it stops updating it in a year's time? And all your pages are stored in a database in the specific format of whatever system you are using, so if you started out with Drupal but now think Wordpress might be a better idea, you have a world of pain.
Why use a static site?
If you site contains static content, there are a number of advantages to using a static site generator rather than a dynamic CMS. The full source of the website is stored offline, as a collection of text files, so:
- All your files can be backed up easily, you don't need to worry about the complexities of backing up a data base.
- You can use any text editor you like to create content.
- Your content is in a simple, generic format so if you decide to make changes to your system later it will be easy to convert you content.
- You can use standard tools (or create simple python scripts) to perform searches and bulk changes.
- Ultimately, all your work is stored as text files on your PC, you are always going to be able to access it and transform it to other formats if you need to.
On the server side:
- You can use simple cheap hosting to serve static files.
- Serving static files is faster and uses less server resources.
- CMS software is often complex and needs to be updated periodically to fix security problems.
- Databases (used by most CMS software) are a major source of vulnerabilities.
- The online database is usually where original content is stored. If it is hacked or crashes, your work could be lost.
- Backing up a remote databases is more difficult and error prone than backing up local text files.
- Additional features are often provided by third party plugins. It is always possible that when the main CMS is updated, a compatible version of a plugin might not be available immediately, or might even be discontinued in the future.
- It is very difficult to move an existing site to a new CMS, for example if you have a large Drupal site it is very difficult to convert it to Wordpress.
Why write your own static site generator in Python?
There are quite a few existing static site generators, such as Jekyll (written in Ruby), Hugo (written in Go), and several written in Python (for example Pelican). They are usually well set up to create a simple blog with very little effort, and have a variety of themes available that range from very good to embarrassingly awful. You can also use them for static non-blog sites such as project documentation, company home pages and tutorial sites.
Another plus point is that they tend to store their content in markdown files, often similar to each other and similar to the method we will develop in this series. So you get all the advantages of text based content and the ability to swap between different static site generators relatively easily.
In fact, if you are new to static site generators, you might even decide to start out using an existing one (I personally would recommend Hugo). It won't be that difficult to change to your own site generator later, the content pages should be almost identical.
So why write your own?
The possible problems with third party generators are:
- You are relying on software that you don't control.
- You may also need plugins that you don't control and may be discontinued at some point.
- You may find that different themes have different capabilities, so for example a theme that looks great might not support tags.
- Adding your own features often involves a lot more work than you would really expect.
- At some point you will find yourself writing some long and convoluted template code to do something that would take a few simple lines of Python.
The benefits of writing your own are:
- Writing a static site generator in Python is surprisingly easy.
- It is a fun little project.
- You will have complete control of how your website is created.
- Non-standard requirements are usually quite doable
In the next few articles we will see how to write a fully featured static site generator in Python.
Join the PythonInformer Newsletter
Sign up using this form to receive an email when new content is added:
2d arrays abstract data type alignment and angle animation arc array arrays bar chart bar style behavioural pattern bezier curve built-in function callable object chain circle classes clipping close closure cmyk colour combinations comparison operator comprehension context context manager conversion count creational pattern data science data types decorator design pattern device space dictionary drawing duck typing efficiency ellipse else encryption enumerate fill filter font font style for loop formula function function composition function plot functools game development generativepy tutorial generator geometry gif global variable gradient greyscale higher order function hsl html image image processing imagesurface immutable object in operator index inner function input installing iter iterable iterator itertools join l system lambda function latex len lerp line line plot line style linear gradient linspace list list comprehension logical operator lru_cache magic method mandelbrot mandelbrot set map marker style matplotlib monad mutability named parameter numeric python numpy object open operator optimisation optional parameter or pandas partial application path pattern permutations pie chart pil pillow polygon pong positional parameter print product programming paradigms programming techniques pure function python standard library radial gradient range recipes rectangle recursion reduce regular polygon repeat rgb rotation roundrect scaling scatter plot scipy sector segment sequence setup shape singleton slice slicing sound spirograph sprite square str stream string stroke structural pattern subpath symmetric encryption template tex text text metrics tinkerbell fractal transform translation transparency triangle truthy value tuple turtle unpacking user space vectorisation webserver website while loop zip zip_longest