Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions djangoproject/scss/_style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3318,6 +3318,20 @@ hr {
}
}

/* Improve accessibility for footnote links in tables */
table sup a,
.django-supported-versions sup a,
.django-unsupported-versions sup a {
color: var(--link-color);
text-decoration: underline;

&:hover,
&:focus {
color: var(--primary-accent);
text-decoration: underline;
}
}

form .footnote {
margin-top: 10px;
text-align: left;
Expand Down
1 change: 1 addition & 0 deletions djangoproject/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
FIXTURE_DIRS = [str(PROJECT_PACKAGE.joinpath("fixtures"))]

INSTALLED_APPS = [
"djangoproject", # Add main project app for template tags
"accounts",
"aggregator",
"blog",
Expand Down
97 changes: 97 additions & 0 deletions djangoproject/templates/base_lite.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{% load static %}<!DOCTYPE html>
<html lang="{% block html_language_code %}en{% endblock %}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="ROBOTS" content="ALL" />
<meta name="MSSmartTagsPreventParsing" content="true" />
<meta name="Copyright" content="Django Software Foundation" />
<meta name="keywords" content="{% block keywords %}Python, Django, framework, open-source{% endblock %}" />
<meta name="description" content="{% block description %}{% endblock %}" />
<meta name="fediverse:creator" content="@[email protected]" />
{% block link_rel_tags %}{% endblock link_rel_tags %}

<!-- Favicons -->
<link rel="apple-touch-icon" href="{% static "img/icon-touch.png" %}">
<link rel="icon" sizes="192x192" href="{% static "img/icon-touch.png" %}">
<link rel="shortcut icon" href="{% static "img/favicon.ico" %}">
<meta name="msapplication-TileColor" content="#113228">
<meta name="msapplication-TileImage" content="{% static "img/icon-tile.png" %}">
<meta name="theme-color" content="#0C4B33">

{% block og_tags %}
<meta property="og:title" content="{% block og_title %}Django{% endblock %}" />
<meta property="og:description" content="{% block og_description %}{% spaceless %}
The web framework for perfectionists with deadlines.
{% endspaceless %}{% endblock %}" />
<meta property="og:image" content="{% block og_image %}{% static "img/logos/django-logo-negative.png" %}{% endblock %}" />
<meta property="og:image:alt" content="{% block og_image_alt %}Django logo{% endblock %}" />
<meta property="og:image:width" content="{% block og_image_width %}1200{% endblock %}" />
<meta property="og:image:height" content="{% block og_image_height %}546{% endblock %}" />
<meta property="og:image:type" content="image/png" />
<meta property="og:url" content="{{ request.build_absolute_uri }}" />
<meta property="og:site_name" content="Django Project" />

<meta property="twitter:creator" content="djangoproject" />
<meta property="twitter:site" content="djangoproject" />
<meta property="twitter:card" content="{% block twitter_card %}summary{% endblock %}">
{% endblock og_tags %}

<title>{% block title %}Django{% endblock %}</title>

{% comment %}
Custom stylesheets block - allows for completely different styling
By default, no stylesheets are included to allow for custom styling
{% endcomment %}
{% block stylesheets %}
{% comment %}
Example usage:
{% block stylesheets %}
<link rel="stylesheet" href="{% static "css/annual-report.css" %}">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Custom+Font">
{% endblock %}
{% endcomment %}
{% endblock stylesheets %}

{% block head_extra %}{% endblock head_extra %}
</head>

<body id="{% block sectionid %}lite{% endblock %}" class="{% block body_class %}lite-template{% endblock %}">
{% comment %}
Skip link for accessibility - can be overridden if needed
{% endcomment %}
{% block skip_link %}
<a href="#main-content" class="skip-link">Skip to main content</a>
{% endblock skip_link %}

{% comment %}
Optional minimal header - can be completely overridden or omitted
{% endcomment %}
{% block header %}{% endblock header %}

{% comment %}
Main content area - completely flexible
{% endcomment %}
<main id="main-content" {% block main_attributes %}{% endblock main_attributes %}>
{% block content %}{% endblock content %}
</main>

{% comment %}
Optional footer - can be completely overridden or omitted
{% endcomment %}
{% block footer %}{% endblock footer %}

{% comment %}
Minimal JavaScript block - only includes essentials
Can be overridden for custom JS needs
{% endcomment %}
{% block javascript %}
{% comment %}
Add any essential JavaScript here or override completely
{% endcomment %}
{% endblock javascript %}

{% block body_extra %}{% endblock body_extra %}
</body>
</html>
71 changes: 71 additions & 0 deletions djangoproject/templates/flatpages/lite.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{% extends "base_lite.html" %}
{% load static lite_filters %}

{% comment %}
Lite flatpage template for documents with custom styling

This template is designed for one-off documents like annual reports,
special publications, or any content that needs completely different
styling from the main Django website.

Usage:
1. Create your flatpage in Django admin
2. Set the template name to "flatpages/lite.html"
3. Add custom CSS by creating blocks in your content or
by extending this template further

Example custom styling approaches:

Approach 1: Inline styles in flatpage content
<style>
body { background: #f0f0f0; font-family: 'Custom Font'; }
.special-section { color: red; }
</style>

Approach 2: External stylesheet in flatpage content
<link rel="stylesheet" href="{% static 'css/my-custom-report.css' %}">

Approach 3: Create a custom template that extends this one
{% extends "flatpages/lite.html" %}
{% block stylesheets %}
<link rel="stylesheet" href="{% static 'css/annual-report.css' %}">
{% endblock %}
{% endcomment %}

{% block title %}{{ flatpage.title }}{% endblock %}
{% block og_title %}{{ flatpage.title }}{% endblock %}

{% comment %}
Extract CSS and JS from flatpage content if present
This allows content editors to include custom styles directly in the content
{% endcomment %}
{% block stylesheets %}
{% comment %}
Extract any <link> or <style> tags from the beginning of flatpage content
and include them in the head section for proper CSS loading
{% endcomment %}
{{ flatpage.content|extract_head_tags }}
{% endblock stylesheets %}

{% block content %}
{% comment %}
Include the flatpage content with head tags removed
to avoid duplicate CSS/JS includes
If filters fail, fall back to showing full content
{% endcomment %}
{% with cleaned_content=flatpage.content|remove_head_tags|remove_script_tags %}
{% if cleaned_content %}
{{ cleaned_content }}
{% else %}
{{ flatpage.content }}
{% endif %}
{% endwith %}
{% endblock content %}

{% comment %}
Extract any JavaScript from flatpage content and include at bottom
{% endcomment %}
{% block javascript %}
{{ block.super }}
{{ flatpage.content|extract_script_tags }}
{% endblock javascript %}
2 changes: 1 addition & 1 deletion djangoproject/templates/fundraising/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ <h2 id="who-are-the-django-fellows">{% translate "Who are the Django Fellows?" %
{% endblocktranslate %}
</p>

<p>{% translate "Former Django Fellows:" %}</p>
<h3>{% translate "Former Django Fellows:" %}</h3>

<p>
{% blocktranslate trimmed %}
Expand Down
1 change: 1 addition & 0 deletions djangoproject/templatetags/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Template tags for djangoproject
114 changes: 114 additions & 0 deletions djangoproject/templatetags/lite_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"""
Template filters for lite templates

These filters help extract CSS and JavaScript from flatpage content
to properly place them in the document head and footer sections.
"""

import re

from django import template
from django.utils.safestring import mark_safe

register = template.Library()


@register.filter
def extract_head_tags(value):
"""
Extract <link> and <style> tags from HTML content for placement in <head>

Usage: {{ flatpage.content|extract_head_tags }}
"""
if not value:
return ""

# Pattern to match <link> tags (CSS stylesheets, fonts, etc.)
link_pattern = r"<link[^>]*?>"

# Pattern to match <style> tags with their content
style_pattern = r"<style[^>]*?>.*?</style>"

# Find all matches
links = re.findall(link_pattern, value, re.IGNORECASE | re.DOTALL)
styles = re.findall(style_pattern, value, re.IGNORECASE | re.DOTALL)

# Combine and return
head_content = "\n".join(links + styles)
return mark_safe(head_content)


@register.filter
def remove_head_tags(value):
"""
Remove <link> and <style> tags from HTML content to avoid duplication

Usage: {{ flatpage.content|remove_head_tags }}
"""
if not value:
return ""

# Remove <link> tags
value = re.sub(r"<link[^>]*?>", "", value, flags=re.IGNORECASE | re.DOTALL)

# Remove <style> tags and their content
value = re.sub(
r"<style[^>]*?>.*?</style>", "", value, flags=re.IGNORECASE | re.DOTALL
)

return mark_safe(value)


@register.filter
def extract_script_tags(value):
"""
Extract <script> tags from HTML content for placement before </body>

Usage: {{ flatpage.content|extract_script_tags }}
"""
if not value:
return ""

# Pattern to match <script> tags with their content
script_pattern = r"<script[^>]*?>.*?</script>"

# Find all matches
scripts = re.findall(script_pattern, value, re.IGNORECASE | re.DOTALL)

return mark_safe("\n".join(scripts))


@register.filter
def remove_script_tags(value):
"""
Remove <script> tags from HTML content to avoid duplication

Usage: {{ flatpage.content|remove_script_tags }}
"""
if not value:
return ""

# Remove <script> tags and their content
value = re.sub(
r"<script[^>]*?>.*?</script>", "", value, flags=re.IGNORECASE | re.DOTALL
)

return mark_safe(value)


@register.filter
def clean_content_for_lite(value):
"""
Combined filter to clean flatpage content for lite templates
Removes both head tags and script tags

Usage: {{ flatpage.content|clean_content_for_lite }}
"""
if not value:
return ""

# Remove head tags first, then script tags
value = remove_head_tags(value)
value = remove_script_tags(value)

return value