Skip to content

Commit 500173e

Browse files
JacobCoffeeclaude
andauthored
Fix supernav update on save (#2941)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3f06040 commit 500173e

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

apps/downloads/models.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from django.conf import settings
66
from django.core.exceptions import ValidationError
77
from django.db import models
8-
from django.db.models.signals import post_save
8+
from django.db.models.signals import post_delete, post_save
99
from django.dispatch import receiver
1010
from django.template.loader import render_to_string
1111
from django.urls import reverse
@@ -332,6 +332,31 @@ def update_download_supernav_and_boxes(sender, instance, **kwargs):
332332
update_homepage_download_box()
333333

334334

335+
def _update_boxes_for_release_file(instance):
336+
"""Update supernav and download boxes if the file's release is published."""
337+
if instance.release_id and instance.release.is_published:
338+
update_supernav()
339+
update_download_landing_sources_box()
340+
update_homepage_download_box()
341+
purge_url("/box/supernav-python-downloads/")
342+
purge_url("/box/homepage-downloads/")
343+
purge_url("/box/download-sources/")
344+
345+
346+
@receiver(post_save, sender="downloads.ReleaseFile")
347+
def update_boxes_on_release_file_save(sender, instance, **kwargs):
348+
"""Refresh supernav when a release file is added or changed."""
349+
if kwargs.get("raw", False):
350+
return
351+
_update_boxes_for_release_file(instance)
352+
353+
354+
@receiver(post_delete, sender="downloads.ReleaseFile")
355+
def update_boxes_on_release_file_delete(sender, instance, **kwargs):
356+
"""Refresh supernav when a release file is deleted."""
357+
_update_boxes_for_release_file(instance)
358+
359+
335360
class ReleaseFile(ContentManageable, NameSlugModel):
336361
"""Individual files in a release.
337362

apps/downloads/tests/test_models.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime as dt
2+
from unittest.mock import patch
23

34
from apps.downloads.models import Release, ReleaseFile
45
from apps.downloads.tests.base import BaseDownloadTests
@@ -232,3 +233,59 @@ def test_update_supernav_skips_os_without_files(self):
232233

233234
# Android (no files) should not be present
234235
self.assertNotIn("android", content.lower())
236+
237+
@patch("apps.downloads.models.update_supernav")
238+
@patch("apps.downloads.models.update_download_landing_sources_box")
239+
@patch("apps.downloads.models.update_homepage_download_box")
240+
def test_release_file_save_triggers_box_updates(self, mock_home, mock_sources, mock_supernav):
241+
"""Saving a ReleaseFile on a published release should update boxes."""
242+
mock_supernav.reset_mock()
243+
mock_sources.reset_mock()
244+
mock_home.reset_mock()
245+
246+
ReleaseFile.objects.create(
247+
os=self.windows,
248+
release=self.python_3,
249+
name="Windows installer",
250+
url="/ftp/python/3.10.19/python-3.10.19.exe",
251+
download_button=True,
252+
)
253+
254+
mock_supernav.assert_called()
255+
mock_sources.assert_called()
256+
mock_home.assert_called()
257+
258+
@patch("apps.downloads.models.update_supernav")
259+
@patch("apps.downloads.models.update_download_landing_sources_box")
260+
@patch("apps.downloads.models.update_homepage_download_box")
261+
def test_release_file_save_skips_unpublished_release(self, mock_home, mock_sources, mock_supernav):
262+
"""Saving a ReleaseFile on a draft release should not update boxes."""
263+
mock_supernav.reset_mock()
264+
mock_sources.reset_mock()
265+
mock_home.reset_mock()
266+
267+
ReleaseFile.objects.create(
268+
os=self.windows,
269+
release=self.draft_release,
270+
name="Windows installer draft",
271+
url="/ftp/python/9.7.2/python-9.7.2.exe",
272+
)
273+
274+
mock_supernav.assert_not_called()
275+
mock_sources.assert_not_called()
276+
mock_home.assert_not_called()
277+
278+
@patch("apps.downloads.models.update_supernav")
279+
@patch("apps.downloads.models.update_download_landing_sources_box")
280+
@patch("apps.downloads.models.update_homepage_download_box")
281+
def test_release_file_delete_triggers_box_updates(self, mock_home, mock_sources, mock_supernav):
282+
"""Deleting a ReleaseFile on a published release should update boxes."""
283+
mock_supernav.reset_mock()
284+
mock_sources.reset_mock()
285+
mock_home.reset_mock()
286+
287+
self.release_275_windows_32bit.delete()
288+
289+
mock_supernav.assert_called()
290+
mock_sources.assert_called()
291+
mock_home.assert_called()

0 commit comments

Comments
 (0)