From 263227cb2d20b0b4f683e42b52758a56e941a6d9 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 23 Apr 2025 15:30:33 +0100 Subject: [PATCH 1/6] [WIP] Update website for Python install manager --- downloads/managers.py | 13 +++++++++++++ downloads/models.py | 6 ++++++ downloads/urls.py | 1 + downloads/views.py | 21 +++++++++++++++++++++ templates/downloads/index.html | 9 +++++++++ templates/downloads/os_list.html | 12 +++++++++++- templates/downloads/supernav.html | 7 ++++++- 7 files changed, 67 insertions(+), 2 deletions(-) diff --git a/downloads/managers.py b/downloads/managers.py index b529dcdd4..56040d2bb 100644 --- a/downloads/managers.py +++ b/downloads/managers.py @@ -23,12 +23,18 @@ def python2(self): def python3(self): return self.filter(version=3, is_published=True) + def pymanager(self): + return self.filter(version=100, is_published=True) + def latest_python2(self): return self.python2().filter(is_latest=True) def latest_python3(self): return self.python3().filter(is_latest=True) + def latest_pymanager(self): + return self.pymanager().filter(is_latest=True) + def pre_release(self): return self.filter(pre_release=True) @@ -50,3 +56,10 @@ def latest_python3(self): return qs[0] else: return None + + def latest_pymanager(self): + qs = self.get_queryset().latest_pymanager() + if qs: + return qs[0] + else: + return None diff --git a/downloads/models.py b/downloads/models.py index 415804b6e..3c0a74f97 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -45,10 +45,12 @@ class Release(ContentManageable, NameSlugModel): PYTHON1 = 1 PYTHON2 = 2 PYTHON3 = 3 + PYMANAGER = 100 PYTHON_VERSION_CHOICES = ( (PYTHON3, 'Python 3.x.x'), (PYTHON2, 'Python 2.x.x'), (PYTHON1, 'Python 1.x.x'), + (PYMANAGER, 'Python install manager'), ) version = models.IntegerField(default=PYTHON3, choices=PYTHON_VERSION_CHOICES) is_latest = models.BooleanField( @@ -146,6 +148,10 @@ def is_version_at_least_3_5(self): def is_version_at_least_3_9(self): return self.is_version_at_least((3, 9)) + @property + def is_version_at_least_3_14(self): + return self.is_version_at_least((3, 14)) + def update_supernav(): latest_python3 = Release.objects.latest_python3() diff --git a/downloads/urls.py b/downloads/urls.py index eddef7a10..5b6b3fda0 100644 --- a/downloads/urls.py +++ b/downloads/urls.py @@ -5,6 +5,7 @@ urlpatterns = [ re_path(r'latest/python2/?$', views.DownloadLatestPython2.as_view(), name='download_latest_python2'), re_path(r'latest/python3/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), + re_path(r'latest/pymanager/?$', views.DownloadLatestPyManager.as_view(), name='download_latest_pymanager'), re_path(r'latest/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), path('operating-systems/', views.DownloadFullOSList.as_view(), name='download_full_os_list'), path('release//', views.DownloadReleaseDetail.as_view(), name='download_release_detail'), diff --git a/downloads/views.py b/downloads/views.py index 2e48cb2f3..816ad3b2e 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -45,6 +45,22 @@ def get_redirect_url(self, **kwargs): return reverse('download') +class DownloadLatestPyManager(RedirectView): + """ Redirect to latest Python install manager release """ + permanent = False + + def get_redirect_url(self, **kwargs): + try: + latest_pymanager = Release.objects.latest_pymanager() + except Release.DoesNotExist: + latest_pymanager = None + + if latest_pymanager: + return latest_pymanager.get_absolute_url() + else: + return reverse('download') + + class DownloadBase: """ Include latest releases in all views """ def get_context_data(self, **kwargs): @@ -52,6 +68,7 @@ def get_context_data(self, **kwargs): context.update({ 'latest_python2': Release.objects.latest_python2(), 'latest_python3': Release.objects.latest_python3(), + 'latest_pymanager': Release.objects.latest_pymanager(), }) return context @@ -71,6 +88,8 @@ def get_context_data(self, **kwargs): except Release.DoesNotExist: latest_python3 = None + latest_pymanager = context.get('latest_pymanager') + python_files = [] for o in OS.objects.all(): data = { @@ -80,6 +99,8 @@ def get_context_data(self, **kwargs): data['python2'] = latest_python2.download_file_for_os(o.slug) if latest_python3 is not None: data['python3'] = latest_python3.download_file_for_os(o.slug) + if latest_pymanager is not None: + data['pymanager'] = latest_pymanager.download_file_for_os(o.slug) python_files.append(data) context.update({ diff --git a/templates/downloads/index.html b/templates/downloads/index.html index 4cd8155e1..c8de67bff 100644 --- a/templates/downloads/index.html +++ b/templates/downloads/index.html @@ -17,11 +17,20 @@

Download the latest source release

{% else %}

Download the latest version for {{ data.os.name }}

{% endif %} + {% if data.pymanager %} +

+ Download Python install manager +

+ {% if data.python3 %} +

Or get the standalone installer for Download {{ data.python3.release.name }}

+ {% endif %} + {% else %}

{% if data.python3 %} Download {{ data.python3.release.name }} {% endif %}

+ {% endif %} {% endfor %}
diff --git a/templates/downloads/os_list.html b/templates/downloads/os_list.html index 1e0177dca..13eb6ca7e 100644 --- a/templates/downloads/os_list.html +++ b/templates/downloads/os_list.html @@ -29,6 +29,10 @@

Python Releases for {{ os.name }}

@@ -39,7 +43,13 @@

Stable Releases

  • {{ r.name }} - {{ r.release_date|date }} {% if os.slug == 'windows' %} - {% if r.is_version_at_least_3_9 %} + {% if r.is_version_at_least_3_14 %} + {% if latest_pymanager %} +

    Download using the Python install manager.

    + {% else %} +

    Download using the Python install manager.

    + {% elif %} + {% elif r.is_version_at_least_3_9 %}

    Note that {{ r.name }} cannot be used on Windows 7 or earlier.

    {% elif r.is_version_at_least_3_5 %}

    Note that {{ r.name }} cannot be used on Windows XP or earlier.

    diff --git a/templates/downloads/supernav.html b/templates/downloads/supernav.html index fb0a1e629..072db029e 100644 --- a/templates/downloads/supernav.html +++ b/templates/downloads/supernav.html @@ -7,10 +7,15 @@

    Python Source

    {% else %}

    Download for {{ data.os.name }}

    {% endif %} + + {% if data.pymanager %} +

    Python install manager

    +

    Or get the standalone installer for {{ data.python3.release.name }}

    + {% else %}

    {{ data.python3.release.name }}

    - {% if data.os.slug == 'windows' %}

    Note that Python 3.9+ cannot be used on Windows 7 or earlier.

    {% endif %} + {% endif %}

    Not the OS you are looking for? Python can be used on many operating systems and environments. View the full list of downloads.

  • {% endfor %} From e2ae26a4f5187d97bfe11283053813cc2f192f56 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Thu, 24 Apr 2025 13:22:19 +0100 Subject: [PATCH 2/6] Stray 'Download' --- templates/downloads/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/downloads/index.html b/templates/downloads/index.html index c8de67bff..f527be031 100644 --- a/templates/downloads/index.html +++ b/templates/downloads/index.html @@ -22,7 +22,7 @@

    Download the latest version for {{ data.os.name }}Download Python install manager

    {% if data.python3 %} -

    Or get the standalone installer for Download {{ data.python3.release.name }}

    +

    Or get the standalone installer for {{ data.python3.release.name }}

    {% endif %} {% else %}

    From b1837426ef22e5f6b6ad45cac6ed6875cc5756db Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Thu, 24 Apr 2025 20:26:33 +0100 Subject: [PATCH 3/6] Add migration --- .../migrations/0012_alter_release_version.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 downloads/migrations/0012_alter_release_version.py diff --git a/downloads/migrations/0012_alter_release_version.py b/downloads/migrations/0012_alter_release_version.py new file mode 100644 index 000000000..e6aea4d1f --- /dev/null +++ b/downloads/migrations/0012_alter_release_version.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.20 on 2025-04-24 19:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('downloads', '0011_alter_os_creator_alter_os_last_modified_by_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='release', + name='version', + field=models.IntegerField(choices=[(3, 'Python 3.x.x'), (2, 'Python 2.x.x'), (1, 'Python 1.x.x'), (100, 'Python install manager')], default=3), + ), + ] From 932b79edc790f73c756e447d7c36115ef2b8e4ab Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Thu, 24 Apr 2025 20:32:46 +0100 Subject: [PATCH 4/6] Fix template --- base-requirements.txt | 4 ++-- templates/downloads/os_list.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base-requirements.txt b/base-requirements.txt index aa4e0f4e0..ef21acc02 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -9,11 +9,11 @@ docutils==0.21.2 Markdown==3.7 cmarkgfm==0.6.0 Pillow==10.4.0 -psycopg2-binary==2.9.9 +#psycopg2-binary==2.9.9 python3-openid==3.2.0 python-decouple==3.8 # lxml used by BeautifulSoup. -lxml==5.2.2 +lxml==5.4.0 cssselect==1.2.0 feedparser==6.0.11 beautifulsoup4==4.12.3 diff --git a/templates/downloads/os_list.html b/templates/downloads/os_list.html index 13eb6ca7e..4a4b177e1 100644 --- a/templates/downloads/os_list.html +++ b/templates/downloads/os_list.html @@ -48,7 +48,7 @@

    Stable Releases

    Download using the Python install manager.

    {% else %}

    Download using the Python install manager.

    - {% elif %} + {% endif %} {% elif r.is_version_at_least_3_9 %}

    Note that {{ r.name }} cannot be used on Windows 7 or earlier.

    {% elif r.is_version_at_least_3_5 %} From e675b8e4c9ff04e07aacd4a5c9a2b615699197d2 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Thu, 24 Apr 2025 20:35:01 +0100 Subject: [PATCH 5/6] Revert requirements change --- base-requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base-requirements.txt b/base-requirements.txt index ef21acc02..aa4e0f4e0 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -9,11 +9,11 @@ docutils==0.21.2 Markdown==3.7 cmarkgfm==0.6.0 Pillow==10.4.0 -#psycopg2-binary==2.9.9 +psycopg2-binary==2.9.9 python3-openid==3.2.0 python-decouple==3.8 # lxml used by BeautifulSoup. -lxml==5.4.0 +lxml==5.2.2 cssselect==1.2.0 feedparser==6.0.11 beautifulsoup4==4.12.3 From 5010aebb53b78938837dd0746a5af116b0afe0d8 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 25 Apr 2025 18:06:04 +0100 Subject: [PATCH 6/6] Update templates to be unchanged when no PyManager is available --- templates/downloads/os_list.html | 2 +- templates/downloads/supernav.html | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/downloads/os_list.html b/templates/downloads/os_list.html index 4a4b177e1..ffd524e5f 100644 --- a/templates/downloads/os_list.html +++ b/templates/downloads/os_list.html @@ -43,7 +43,7 @@

    Stable Releases

  • {{ r.name }} - {{ r.release_date|date }} {% if os.slug == 'windows' %} - {% if r.is_version_at_least_3_14 %} + {% if latest_pymanager and r.is_version_at_least_3_14 %} {% if latest_pymanager %}

    Download using the Python install manager.

    {% else %} diff --git a/templates/downloads/supernav.html b/templates/downloads/supernav.html index 072db029e..12568eadb 100644 --- a/templates/downloads/supernav.html +++ b/templates/downloads/supernav.html @@ -15,6 +15,7 @@

    Download for {{ data.os.name }}

    {{ data.python3.release.name }}

    + {% if data.os.slug == 'windows' %}

    Note that Python 3.9+ cannot be used on Windows 7 or earlier.

    {% endif %} {% endif %}

    Not the OS you are looking for? Python can be used on many operating systems and environments. View the full list of downloads.