Skip to content

Commit

Permalink
Fix serving static files from third-party services. #384 #385
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiocaccamo committed Oct 17, 2024
1 parent 4dc34e3 commit 36c7f5b
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 57 deletions.
64 changes: 31 additions & 33 deletions admin_interface/templates/admin/base_site.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

{% block extrastyle %}
{% get_admin_interface_theme as theme %}
{% get_admin_interface_nocache as version_md5_cache %}
{% get_current_language as current_lang %}
<style>
:root .admin-interface {
Expand Down Expand Up @@ -79,39 +78,39 @@
{% endif %}
}
</style>
<link rel="stylesheet" href="{% static 'admin_interface/css/admin-interface.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/changelist.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/change-form.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/fieldsets.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/file-upload.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/header.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/inlines.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/jquery.ui.tabs.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/language-chooser.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/list-filter.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/list-filter-dropdown.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/login.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/modules.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/nav-sidebar.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/paginator.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/object-tools.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/admin-interface.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/changelist.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/change-form.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/fieldsets.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/file-upload.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/header.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/inlines.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/jquery.ui.tabs.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/language-chooser.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/list-filter.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/list-filter-dropdown.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/login.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/modules.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/nav-sidebar.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/paginator.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/object-tools.css' %}">
{% if not theme.recent_actions_visible %}
<link rel="stylesheet" href="{% static 'admin_interface/css/recent-actions.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/recent-actions.css' %}">
{% endif %}
<link rel="stylesheet" href="{% static 'admin_interface/css/rtl.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/sticky-form-controls.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/tabbed-changeform.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/widgets.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/rtl.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/sticky-form-controls.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/tabbed-changeform.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/widgets.css' %}">

<!-- third-party packages compatibility / style optimizations -->
<link rel="stylesheet" href="{% static 'admin_interface/css/third-party/ckeditor.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/third-party/import-export.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/third-party/json-widget.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/third-party/modeltranslation.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/third-party/rangefilter.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/third-party/sorl-thumbnail.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/third-party/streamfield.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin_interface/css/third-party/tinymce.css' %}?v={{ version_md5_cache }}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/third-party/ckeditor.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/third-party/import-export.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/third-party/json-widget.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/third-party/modeltranslation.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/third-party/rangefilter.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/third-party/sorl-thumbnail.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/third-party/streamfield.css' %}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin_interface/css/third-party/tinymce.css' %}">
<!-- end third-party packages compatibility / style optimizations -->

{% if current_lang == 'fa' %}
Expand All @@ -123,11 +122,10 @@
{% block blockbots %}
{{ block.super }}
{% get_admin_interface_theme as theme %}
{% get_admin_interface_nocache as version_md5_cache %}
{# https://github.com/elky/django-flat-responsive#important-note #}
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" href="{% static 'admin/css/responsive.css' %}?nocache={{ version_md5_cache }}">
<link rel="stylesheet" href="{% static 'admin/css/responsive_rtl.css' %}?nocache={{ version_md5_cache }}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin/css/responsive.css' %}?nocache={{ version_md5_cache }}">
<link rel="stylesheet" href="{% get_admin_interface_static 'admin/css/responsive_rtl.css' %}?nocache={{ version_md5_cache }}">
{% include "admin_interface/favicon.html" %}
{% include "admin_interface/foldable-apps.html" %}
{% include "admin_interface/related-modal.html" %}
Expand Down
16 changes: 8 additions & 8 deletions admin_interface/templatetags/admin_interface_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django import template
from django.conf import settings
from django.contrib.admin.utils import get_fields_from_path
from django.templatetags.static import static
from django.urls import NoReverseMatch, reverse
from django.utils import translation
from slugify import slugify
Expand Down Expand Up @@ -81,20 +82,19 @@ def get_admin_interface_inline_template(template):
return "/".join(template_path)


@register.simple_tag()
def get_admin_interface_version():
return __version__


def hash_string(text):
hash_object = hashlib.sha224(text.encode())
sha224_hash = hash_object.hexdigest()
return sha224_hash


@register.simple_tag()
def get_admin_interface_nocache():
return hash_string(__version__)
@register.simple_tag(takes_context=False)
def get_admin_interface_static(path):
url = static(path)
if not url.startswith(("https://", "http://", "//")):
version_hash = hash_string(__version__)
url = f"{url}?v={version_hash}"
return url


@register.simple_tag(takes_context=False)
Expand Down
28 changes: 12 additions & 16 deletions tests/test_templatetags.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
from datetime import date
from unittest.mock import Mock

from django.conf import settings
from django.contrib.admin.views.main import ChangeList
from django.template import Context, Template
from django.test import TestCase, override_settings
from django.test.client import RequestFactory

from admin_interface.metadata import __version__
from admin_interface.models import Theme
from admin_interface.templatetags import admin_interface_tags as templatetags
from admin_interface.templatetags.admin_interface_tags import hash_string


class AdminInterfaceTemplateTagsTestCase(TestCase):
Expand Down Expand Up @@ -104,27 +103,24 @@ def test_get_setting(self):
title = templatetags.get_admin_interface_setting("title")
self.assertEqual(title, "Django administration")

def test_get_version(self):
version = templatetags.get_admin_interface_version()
self.assertEqual(version, __version__)
def test_get_static(self):
path = "admin_interface/css/admin-interface.css"
rendered = self.__render_template(
"{% load admin_interface_tags %}"
"{% get_admin_interface_version as version %}"
"{{ version }}"
f"{{% get_admin_interface_static '{path}' %}}"
)
self.assertEqual(rendered, __version__)

def test_get_version_nocache(self):
hash_from_tag = templatetags.get_admin_interface_nocache()
hash_manual = hash_string(__version__)
self.assertEqual(hash_from_tag, hash_manual)
self.assertTrue(rendered.startswith(f"{settings.STATIC_URL}{path}?v="))

@override_settings(
STATIC_URL="https://bucket.s3.amazonaws.com/static/",
)
def test_get_static_with_s3_url(self):
path = "admin_interface/css/admin-interface.css"
rendered = self.__render_template(
"{% load admin_interface_tags %}"
"{% get_admin_interface_nocache as version_md5_hash %}"
"{{ version_md5_hash }}"
f"{{% get_admin_interface_static '{path}' %}}"
)
self.assertEqual(rendered, hash_manual)
self.assertEqual(rendered, f"{settings.STATIC_URL}{path}")

def test_get_admin_interface_inline_template(self):
headless_template = templatetags.get_admin_interface_inline_template(
Expand Down

1 comment on commit 36c7f5b

@merwok
Copy link
Contributor

@merwok merwok commented on 36c7f5b Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabiocaccamo On lines 127-128, ?{{ version_md5_cache }} were not removed
(found (I think) thanks to pytest-django that turns unknown template variables into errors)

Please sign in to comment.