Skip to main content

django-snakeoil

django-snakeoil helps manage your <meta> tags. It works on all supported Django versions and databases.

It offers full internationalization support (tags for multiple languages), content set dynamically from object attributes, automatic Opengraph image width and heights for ImageField, and more.

Full documentation

Getting started

To install, pip install django-snakeoil or use your favourite package manager.

You can use Snakeoil in two ways. If you’d like to attach metadata to an object, you can use the model abstract base class:

from snakeoil.models import SEOModel

class Article(SEOModel):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    main_image = models.Imagefield(blank=True, null=True)

    @property
    def author_name(self):
        return

    @property
    def snakeoil_metadata(self):
        metadata = {
            "default": [
                {
                    "name": "author",
                    "content": self.author.get_full_name(),
                },
                {"property": "og:title", "content": self.title},
            ]
        }
        if self.main_image:
            metadata["default"].append(
                {"property": "og:image", "attribute": "main_image"}
            )
        return metadata

You can also override these tags in the admin per-object.

For situations where you can’t change the model (flatpages, third party apps) or don’t have one at all, there is an SEOPath model that maps paths to your meta tags.

Tags are added in the admin (or however else you like) as JSON. For example:

{
    "default": [
        {"name": "description", "property": "og:description", "content": "Meta description"},
        {"property": "og:title", "content": "My blog post"},
        {"name": "author", "attribute": "author_name"},
        {"property": "og:image", "static": "img/default.jpg"}
    ]
}

Where default will work for any language. You can replace default with a language code, e.g. “nl_NL”, and these tags will only display if the current language is Dutch. This will generate something like:

<meta name="description" property="og:description" content="Meta description">
<meta property="og:title" "content="My blog post">
<!-- from my_object.author_name -->
<meta name="author" content="Tom Carrick">
<!-- build a static URL -->
<meta property="og:image" content="/static/img/default.jpg">

Note that when using static, width and height are not added, but you may add these yourself. For ImageField, this will be added automatically:

{
    "default": [
        {"property": "og:image", "attribute": "main_image"}
    ]
}

Results in:

<meta property="og:image" content="/media/blog_1_main_image.jpg">
<meta property="og:image:width" content="640">
<meta property="og:image:height" content="480">

Django Templates

Add snakeoil to your INSTALLED_APPS:

INSTALLED_APPS = [
    "snakeoil",
    # ...
]

In your base template, add this where you want the tags to appear:

{% load snakeoil %}
{% block head %}
    {% meta %}
{% endblock %}

This will automatically find an object based on the get_absolute_url() of your model, by looking in the request context. If nothing is found, snakeoil will check for an SEOPath object for the current path. If you have an object, it is recommended to pass it into the tag directly to short-circuit the tag finding mechanisms:

{% meta my_obj %}

Jinja2

Set your environment:

from jinja2 import Environment
from snakeoil.jinja2 import get_meta_tags

def environment(**options):
    env = Environment(**options)
    env.globals.update(
        {
            "get_meta_tags": get_meta_tags,
            # ...
        }
    )
    return env

In your template:

{% block meta %}
    {% with meta_tags=get_meta_tags() %}
        {% include "snakeoil/seo.jinja2" %}
    {% endwith %}
{% endblock meta %}

To pass in an object:

{% block meta %}
    {% with meta_tags=get_meta_tags(my_object) %}
        {% include "snakeoil/seo.jinja2" %}
    {% endwith %}
{% endblock meta %}

Notes

Thanks to kezabelle for the name. For those wondering:

Metadata is often used for SEO purposes. A lot of people (rightly or not) consider SEO to be snakeoil. Also, SnakEOil. Very clever, I know.

The old version of django-snakeoil can be found on the old branch, but won’t be updated.

Metadata

Release files for django-snakeoil 2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-snakeoil 2.0
File Size Uploaded Provenance
django_snakeoil-2.0.tar.gz 13.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-snakeoil 2.0
File Interpreter ABI Platform
django_snakeoil-2.0-py3-none-any.whl Python 3 none any Details

Total release size: 25.0 kB

Release files / django_snakeoil-2.0.tar.gz

Download URL django_snakeoil-2.0.tar.gz
Size 13.8 kB
Tags Source
SHA-256 checksum
How to use checksums
f8194d971af029ef5107171328ebd741e197d204055f719250ccb31423c78cac
BLAKE2b-256 checksum
How to use checksums
8e14b1a618a8fca2d7b9c137e7da00fe702570edd596d6cae270ac8612dbcf57
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.1.1 CPython/3.12.7

Release files / django_snakeoil-2.0-py3-none-any.whl

Download URL django_snakeoil-2.0-py3-none-any.whl
Size 11.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
19b6f28beafe4e743877f1df0f5bf7184b56bfe285f484860ba6c4f336646d79
BLAKE2b-256 checksum
How to use checksums
7957899fb4d389705c04d4694c8866b11109d0e05b21c52e6341e272c11174d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.1.1 CPython/3.12.7

Security for django-snakeoil 2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page