Usage - h-janes/flask-sitemapper GitHub Wiki

The main feature of this extension is the Sitemapper class, which creates and manages a single sitemap (or sitemap index). If you want to have multiple sitemaps in your project, you must create a Sitemapper instance for each.

Initialising

The sitemapper must be initialised with the app instance as shown below.

By default, HTTPS will be used for all URLs in the sitemap. To change this, specify https=False when creating the Sitemapper instance.

Recommended Method

import flask
from flask_sitemapper import Sitemapper

# create sitemapper instance
sitemapper = Sitemapper()

# create app
app = flask.Flask("test_app")

# initialise with app
sitemapper.init_app(app)

Alternative Method

import flask
from flask_sitemapper import Sitemapper

# create app
app = flask.Flask("test_app")

# create instance and initialise with app
sitemapper = Sitemapper(app)

Adding URLs to the Sitemap

Decorators are added to route functions to include their URLs in the sitemap. These must be included above the Flask decorators.

# Define the homepage route and include it in the sitemap
@sitemapper.include()
@app.route("/")
def r_home():
    return flask.render_template("index.html")

Additional Arguments

You can pass optional arguments to the decorator to include additional information in the sitemap. Valid arguments are listed below, as defined by the sitemap protocol:

  • lastmod - The date on which this page was last modified as a string in W3C datetime format (e.g. YYYY-MM-DD), or as a Python datetime object.

  • changefreq - How frequently the page is likely to change as a string. Acceptable values are:

    • always
    • hourly
    • daily
    • weekly
    • monthly
    • yearly
    • never
  • priority - The priority of this URL relative to other URLs on your site as a string, float, or integer. Valid values range from 0.0 to 1.0

@sitemapper.include(
    lastmod = "2022-02-08",
    changefreq = "monthly",
    priority = 1.0,
)
@app.route("/about")
def r_about():
    return flask.render_template("about.html")

Dynamic Routes

Flask Sitemapper can be used with dynamic Flask routes, such as:

@app.route("/user/<int:user_id>")
def r_user(user_id):
    return f"<h1>User #{user_id}</h1>"

To add dynamic routes to your sitemap, you must provide the url_variables argument to the include decorator. This argument is a dictionary where the keys are the name(s) of your URL variable(s) for that route, and the values are lists of values for the URL variables. Other arguments like lastmod can still be provided.

@sitemapper.include(url_variables={"user_id": [1, 2, 3]}, lastmod="2023-09-09")
@app.route("/user/<int:user_id>")
def r_user(user_id):
    return f"<h1>User #{user_id}</h1>"

Here is an example for a route with multiple URL variables and the sitemap that it would generate:

@sitemapper.include(url_variables={"user_id": [1, 2, 3], "post_id": [4, 5, 5]})
@app.route("/post/<int:user_id>_<int:post_id>")
def r_post(user_id, post_id):
    return f"<h1>Post #{post_id} by user #{user_id}</h1>"
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://localhost/post/1_4</loc>
  </url>
  <url>
    <loc>https://localhost/post/2_5</loc>
  </url>
  <url>
    <loc>https://localhost/post/3_5</loc>
  </url>
</urlset>

lastmod, changefreq, and priority arguments can be set as normal or can be set differently per URL variable by providing a list as shown below.

# setting lastmod for all 
@sitemapper.include(
  url_variables={"user_id": [1, 2, 3]},
  lastmod=["2023-09-09", "2023-08-14", "2022-01-20"],
)
@app.route("/user/<int:user_id>")
def r_user(user_id):
    return f"<h1>User #{user_id}</h1>"

You can also use a Callable to generate the dict of url_variables upon each request to the sitemap page. If you provide a Callable, it must return a dict of the same format as above. The callable will be run upon every request, within the app context. Example below:

def generate_user_ids():
    # example - gets all user ids from an SQLAlchemy model `User`
    users = User.query.all()
    return {"user_id": [usr.id for usr in users]}

@sitemapper.include(url_variables=generate_user_ids)
@app.route("/user/<int:user_id>")
def r_user(user_id):
    return f"<h1>User #{user_id}</h1>"

Here is a full example using dynamic routes:

"""
This script sets up a Flask web application with a sitemap generator.
The application includes the following routes:
- `/user/<int:user_id>`: Displays an HTML header for a user with the given user ID.
- `/sitemap.xml` and `/`: Generates and returns a sitemap.
Functions:
- generate_user_ids(): Generates a dictionary containing a list of 5 random user IDs.
- r_user(user_id): Generates an HTML header for a user.
- r_sitemap(): Generates and returns a sitemap.
Modules:
- random: Provides functions to generate random numbers.
- flask: A micro web framework for Python.
- flask_sitemapper: A Flask extension for generating sitemaps.
Classes:
- Sitemapper: A class from the `flask_sitemapper` module used to generate sitemaps.
Attributes:
- sitemapper: An instance of the `Sitemapper` class.
- app: An instance of the `Flask` class.
"""

import random

from flask import Flask
from flask_sitemapper import Sitemapper


def generate_user_ids():
    """
    Generates a dictionary containing a list of 5 random user IDs.

    The function generates a list of 5 random integers between 1 and 10 (inclusive)
    and returns a dictionary with the key 'user_id' and the list of random integers as the value.

    Returns:
        dict: A dictionary with a single key 'user_id' and a list of 5 random integers as the value.
    """
    random_integers = [random.randint(1, 10) for _ in range(5)]
    print(random_integers)
    return {"user_id": random_integers}

sitemapper = Sitemapper()

app = Flask(__name__)
sitemapper.init_app(app)

@sitemapper.include(url_variables=generate_user_ids)
@app.route("/user/<int:user_id>")
def r_user(user_id):
    """
    Generate an HTML header for a user.

    Args:
        user_id (int): The ID of the user.

    Returns:
        str: An HTML string containing the user ID in an <h1> tag.
    """
    return f"<h1>User #{user_id}</h1>"

@app.route("/sitemap.xml")
@app.route("/")
def r_sitemap():
    """
    Generates and returns a sitemap.

    This function calls the `generate` method from the `sitemapper` module
    to create a sitemap.

    Returns:
        object: The generated sitemap.
    """
    return sitemapper.generate()

app.run("127.0.0.1", 8000)

Notes

For routes where multiple URL paths are defined, the sitemap will only include the last path.

@sitemapper.include()
@app.route("/shop")  # This won't be included
@app.route("/buy")  # This won't be included
@app.route("/store")  # This will be included
def r_store():
    return "<h1>Store Page</h1>"

Generating and Serving the Sitemap

To serve your sitemap, you must define a route function that returns sitemapper.generate(). Your sitemap will then be available at the URL(s) you specify.

This route should be defined after all routes that are included in the sitemap.

@app.route("/sitemap.xml")
def r_sitemap():
    return sitemapper.generate()

Using GZIP

You can serve your sitemap with GZIP compression by specifying this when calling the generate method. By default, GZIP will not be used.

@app.route("/sitemap.xml")
def r_sitemap():
    return sitemapper.generate(gzip=True)

The sitemap will only be gzipped if the client accepts GZIP encoding. GZIP will also not be used if the response already has a Content-Encoding header, to avoid conflicts with other compression/encoding that you may be using.

Using With Flask blueprints

To use this extension with blueprints:

  • Create your Sitemapper instance(s) in a separate file or otherwise avoiding circular imports.
  • Import and use the instance(s) in your blueprints.
  • Import the instance(s) when creating your flask app and initialise with sitemapper.init_app(app) after registering your blueprints.

Alternatively, you could define a separate sitemapper inside each blueprint, and use a sitemap index to collate these.

You can also add Flask endpoints to the sitemap by using their endpoint name as shown below. Arguments can still be given after the endpoint name. This is not recommended, but may be helpful for some complex projects.

sitemapper.add_endpoint("r_contact", lastmod="2022-02-09")

Sitemap Indexes

Sitemap indexes are sitemaps that list other sitemaps. These are used if a single sitemap would be too large, or sometimes for organizational purposes. You can create a master sitemapper, which generates a sitemap index, by specifying master=True when creating the instance.

Note that sitemap indexes have a different syntax to regular sitemaps, so it is important to provide this argument.

master_sitemapper = Sitemapper(app, master=True)

You can then decorate your sitemap route functions to add them to the sitemap index.

@master_sitemapper.include()
@app.route("/some_sitemap.xml")
def r_some_sitemap():
    return some_sitemapper.generate()

Or add them with add_endpoint

@master_sitemapper.add_endpoint("r_some_sitemap")

Then create the route for the sitemap index.

@app.route("/sitemap.xml")
def r_sitemap_index():
    return master_sitemapper.generate()
⚠️ **GitHub.com Fallback** ⚠️