Skip to content

Commit f23faa1

Browse files
authored
Merge branch 'main' into shenxianpeng-patch-1
2 parents 7bc1aa1 + 1e92dd5 commit f23faa1

File tree

13 files changed

+99
-5
lines changed

13 files changed

+99
-5
lines changed

base-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4.
44
django-apptemplates==1.5
55
django-admin-interface==0.28.9
66
django-translation-aliases==0.1.0
7-
Django==4.2.20
7+
Django==4.2.21
88
docutils==0.21.2
99
Markdown==3.7
1010
cmarkgfm==0.6.0

downloads/managers.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,18 @@ def python2(self):
2323
def python3(self):
2424
return self.filter(version=3, is_published=True)
2525

26+
def pymanager(self):
27+
return self.filter(version=100, is_published=True)
28+
2629
def latest_python2(self):
2730
return self.python2().filter(is_latest=True)
2831

2932
def latest_python3(self):
3033
return self.python3().filter(is_latest=True)
3134

35+
def latest_pymanager(self):
36+
return self.pymanager().filter(is_latest=True)
37+
3238
def pre_release(self):
3339
return self.filter(pre_release=True)
3440

@@ -50,3 +56,10 @@ def latest_python3(self):
5056
return qs[0]
5157
else:
5258
return None
59+
60+
def latest_pymanager(self):
61+
qs = self.get_queryset().latest_pymanager()
62+
if qs:
63+
return qs[0]
64+
else:
65+
return None
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.2.20 on 2025-04-24 19:26
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('downloads', '0011_alter_os_creator_alter_os_last_modified_by_and_more'),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name='release',
15+
name='version',
16+
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),
17+
),
18+
]

downloads/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ class Release(ContentManageable, NameSlugModel):
4545
PYTHON1 = 1
4646
PYTHON2 = 2
4747
PYTHON3 = 3
48+
PYMANAGER = 100
4849
PYTHON_VERSION_CHOICES = (
4950
(PYTHON3, 'Python 3.x.x'),
5051
(PYTHON2, 'Python 2.x.x'),
5152
(PYTHON1, 'Python 1.x.x'),
53+
(PYMANAGER, 'Python install manager'),
5254
)
5355
version = models.IntegerField(default=PYTHON3, choices=PYTHON_VERSION_CHOICES)
5456
is_latest = models.BooleanField(
@@ -146,6 +148,10 @@ def is_version_at_least_3_5(self):
146148
def is_version_at_least_3_9(self):
147149
return self.is_version_at_least((3, 9))
148150

151+
@property
152+
def is_version_at_least_3_14(self):
153+
return self.is_version_at_least((3, 14))
154+
149155

150156
def update_supernav():
151157
latest_python3 = Release.objects.latest_python3()

downloads/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
urlpatterns = [
66
re_path(r'latest/python2/?$', views.DownloadLatestPython2.as_view(), name='download_latest_python2'),
77
re_path(r'latest/python3/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'),
8+
re_path(r'latest/pymanager/?$', views.DownloadLatestPyManager.as_view(), name='download_latest_pymanager'),
89
re_path(r'latest/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'),
910
path('operating-systems/', views.DownloadFullOSList.as_view(), name='download_full_os_list'),
1011
path('release/<slug:release_slug>/', views.DownloadReleaseDetail.as_view(), name='download_release_detail'),

downloads/views.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,30 @@ def get_redirect_url(self, **kwargs):
4545
return reverse('download')
4646

4747

48+
class DownloadLatestPyManager(RedirectView):
49+
""" Redirect to latest Python install manager release """
50+
permanent = False
51+
52+
def get_redirect_url(self, **kwargs):
53+
try:
54+
latest_pymanager = Release.objects.latest_pymanager()
55+
except Release.DoesNotExist:
56+
latest_pymanager = None
57+
58+
if latest_pymanager:
59+
return latest_pymanager.get_absolute_url()
60+
else:
61+
return reverse('downloads')
62+
63+
4864
class DownloadBase:
4965
""" Include latest releases in all views """
5066
def get_context_data(self, **kwargs):
5167
context = super().get_context_data(**kwargs)
5268
context.update({
5369
'latest_python2': Release.objects.latest_python2(),
5470
'latest_python3': Release.objects.latest_python3(),
71+
'latest_pymanager': Release.objects.latest_pymanager(),
5572
})
5673
return context
5774

@@ -71,6 +88,8 @@ def get_context_data(self, **kwargs):
7188
except Release.DoesNotExist:
7289
latest_python3 = None
7390

91+
latest_pymanager = context.get('latest_pymanager')
92+
7493
python_files = []
7594
for o in OS.objects.all():
7695
data = {
@@ -80,6 +99,8 @@ def get_context_data(self, **kwargs):
8099
data['python2'] = latest_python2.download_file_for_os(o.slug)
81100
if latest_python3 is not None:
82101
data['python3'] = latest_python3.download_file_for_os(o.slug)
102+
if latest_pymanager is not None:
103+
data['pymanager'] = latest_pymanager.download_file_for_os(o.slug)
83104
python_files.append(data)
84105

85106
context.update({

sponsors/api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def get(self, request, *args, **kwargs):
3434
for sponsorship in sponsorships.select_related("sponsor").iterator():
3535
sponsor = sponsorship.sponsor
3636
base_data = {
37+
"sponsor_id": sponsor.id,
3738
"sponsor": sponsor.name,
3839
"sponsor_slug": sponsor.slug,
3940
"level_name": sponsorship.level_name,

sponsors/management/commands/create_pycon_vouchers_for_sponsors.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@ def api_call(uri, query):
6666
scheme = "http" if settings.DEBUG else "https"
6767
url = f"{scheme}://{settings.PYCON_API_HOST}{uri}"
6868
try:
69-
return requests.get(url, headers=headers, params=query).json()
69+
r = requests.get(url, headers=headers, params=query)
70+
return r.json()
7071
except RequestException:
72+
print(r, r.content)
7173
raise
7274

7375

@@ -103,6 +105,7 @@ def generate_voucher_codes(year):
103105
"voucher_type": code["voucher_type"],
104106
"quantity": quantity.quantity,
105107
"sponsor_name": sponsorbenefit.sponsorship.sponsor.name,
108+
"sponsor_id": sponsorbenefit.sponsorship.sponsor.id,
106109
},
107110
)
108111
if result["code"] == 200:

sponsors/serializers.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class LogoPlacementSerializer(serializers.Serializer):
88
publisher = serializers.CharField()
99
flight = serializers.CharField()
1010
sponsor = serializers.CharField()
11+
sponsor_id = serializers.CharField()
1112
sponsor_slug = serializers.CharField()
1213
description = serializers.CharField()
1314
logo = serializers.URLField()

templates/downloads/index.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,20 @@ <h1 class="call-to-action">Download the latest source release</h1>
1717
{% else %}
1818
<h1 class="call-to-action">Download the latest version for {{ data.os.name }}</h1>
1919
{% endif %}
20+
{% if data.pymanager %}
21+
<p class="download-buttons">
22+
<a class="button" href="{{ data.pymanager.url }}">Download Python install manager</a>
23+
</p>
24+
{% if data.python3 %}
25+
<p>Or get the standalone installer for <a href="{{ data.python3.url }}">{{ data.python3.release.name }}</a></p>
26+
{% endif %}
27+
{% else %}
2028
<p class="download-buttons">
2129
{% if data.python3 %}
2230
<a class="button" href="{{ data.python3.url }}">Download {{ data.python3.release.name }}</a>
2331
{% endif %}
2432
</p>
33+
{% endif %}
2534
</div>
2635
{% endfor %}
2736
<div class="download-unknown">

templates/downloads/os_list.html

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ <h1 class="page-title">Python Releases for {{ os.name }}</h1>
2929
</header>
3030

3131
<ul>
32+
{% if os.slug == 'windows' and latest_pymanager %}
33+
<li><a href="{{ latest_pymanager.get_absolute_url }}">Latest Python install manager - {{ latest_pymanager.name }}</a></li>
34+
{% endif %}
35+
3236
<li><a href="{{ latest_python3.get_absolute_url }}">Latest Python 3 Release - {{ latest_python3.name }}</a></li>
3337
</ul>
3438
<div class="col-row two-col">
@@ -39,7 +43,13 @@ <h2>Stable Releases</h2>
3943
<li>
4044
<a href="{{ r.get_absolute_url }}">{{ r.name }} - {{ r.release_date|date }}</a>
4145
{% if os.slug == 'windows' %}
42-
{% if r.is_version_at_least_3_9 %}
46+
{% if latest_pymanager and r.is_version_at_least_3_14 %}
47+
{% if latest_pymanager %}
48+
<p>Download using the <a href="{{ latest_pymanager.get_absolute_url }}">Python install manager</a>.</p>
49+
{% else %}
50+
<p>Download using the <a href="https://docs.python.org/using/windows.html">Python install manager</a>.</p>
51+
{% endif %}
52+
{% elif r.is_version_at_least_3_9 %}
4353
<p><strong>Note that {{ r.name }} <em>cannot</em> be used on Windows 7 or earlier.</strong></p>
4454
{% elif r.is_version_at_least_3_5 %}
4555
<p><strong>Note that {{ r.name }} <em>cannot</em> be used on Windows XP or earlier.</strong></p>

templates/downloads/supernav.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ <h3>Python Source</h3>
77
{% else %}
88
<h4>Download for {{ data.os.name }}</h4>
99
{% endif %}
10+
11+
{% if data.pymanager %}
12+
<p><a class="button" href="{{ data.pymanager.url }}">Python install manager</a></p>
13+
<p>Or get the standalone installer for <a class="button" href="{{ data.python3.url }}">{{ data.python3.release.name }}</a></p>
14+
{% else %}
1015
<p>
1116
<a class="button" href="{{ data.python3.url }}">{{ data.python3.release.name }}</a>
1217
</p>
1318
{% if data.os.slug == 'windows' %}<p><strong>Note that Python 3.9+ <em>cannot</em> be used on Windows 7 or earlier.</strong></p>{% endif %}
19+
{% endif %}
1420
<p>Not the OS you are looking for? Python can be used on many operating systems and environments. <a href="{% url 'download:download' %}">View the full list of downloads</a>.</p>
1521
</div>
1622
{% endfor %}

templates/search/search.html

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ <h3>Results</h3>
1717
{% include result.include_template %}
1818
</li>
1919
{% empty %}
20-
<p>No results found.</p>
20+
<li>No results found.</li>
2121
{% endfor %}
2222
</ul>
2323
{% if page.has_previous or page.has_next %}
@@ -27,8 +27,13 @@ <h3>Results</h3>
2727
{% if page.has_next %}<a href="?q={{ query }}&amp;page={{ page.next_page_number }}">{% endif %}Next &raquo;{% if page.has_next %}</a>{% endif %}
2828
</div>
2929
{% endif %}
30+
31+
<h3>Python language documentation</h3>
32+
<p>If you didn't find what you need, try your search in the
33+
<a href="https://docs.python.org/3/search.html?q={{ request.GET.q | urlencode }}">Python language documentation</a>.
34+
</p>
3035
{% else %}
3136
{# Show some example queries to run, maybe query syntax, something else? #}
3237
{% endif %}
3338
</form>
34-
{% endblock %}
39+
{% endblock %}

0 commit comments

Comments
 (0)