Multi-platform: support multiple files per version #201

Merged
Oleg-Komarov merged 43 commits from multi-os into main 2024-07-09 16:27:46 +02:00
5 changed files with 37 additions and 60 deletions
Showing only changes of commit d55c3c9115 - Show all commits

View File

@ -773,36 +773,22 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
permissions.append({'slug': slug, 'reason': reason, 'name': all_permission_names[slug]})
return permissions
def _get_download_name(self, platform=None) -> str:
def _get_download_name(self, file) -> str:
"""Return a file name for downloads."""
parts = [self.extension.type_slug_singular, self.extension.slug, f'v{self.version}']
if platform:
parts.append(platform)
if platforms := file.get_platforms():
parts.extend(platforms)
return f'{"-".join(parts)}.zip'
def get_download_url(self, platform=None, append_repository_and_compatibility=True) -> str:
filename = self._get_download_name(platform=platform)
if platform:
download_url = reverse(
'extensions:version-platform-download',
kwargs={
'type_slug': self.extension.type_slug,
'slug': self.extension.slug,
'version': self.version,
'platform': platform,
'filename': filename,
},
)
else:
download_url = reverse(
'extensions:version-download',
kwargs={
'type_slug': self.extension.type_slug,
'slug': self.extension.slug,
'version': self.version,
'filename': filename,
},
)
def get_download_url(self, file, append_repository_and_compatibility=True) -> str:
filename = self._get_download_name(file)
download_url = reverse(
'extensions:download',
kwargs={
'filehash': file.hash,
'filename': filename,
},
)
if append_repository_and_compatibility:
params = {
'repository': '/api/v1/extensions/',
@ -810,10 +796,8 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
}
if self.blender_version_max:
params['blender_version_max'] = self.blender_version_max
if platform:
params['platforms'] = platform
elif platforms := self.platforms.all():
params['platforms'] = ','.join([p.slug for p in platforms])
if platforms := file.get_platforms():
params['platforms'] = ','.join(platforms)
query_string = urlencode(params)
download_url += f'?{query_string}'
return download_url
@ -824,9 +808,9 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
file = files[0]
return [
{
'name': self._get_download_name(platform=None),
'name': self._get_download_name(file),
'size': file.size_bytes,
'url': self.get_download_url(platform=None),
'url': self.get_download_url(file),
}
]
platform2file = {}
@ -841,10 +825,10 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
platform2file[platform] = file
return [
{
'name': self._get_download_name(platform=p),
'name': self._get_download_name(file),
'platform': p,
'size': file.size_bytes,
'url': self.get_download_url(platform=p),
'url': self.get_download_url(file),
}
for p, file in platform2file.items()
]
@ -853,15 +837,12 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
build_list = []
for file in self.files.all():
platforms = file.get_platforms() or []
platform = len(platforms) and platforms[0] or None
# if file has multiple platforms, picking the first one should still produce a correct
# download_url
build_list.append(
{
'name': self._get_download_name(platform=platform),
'name': self._get_download_name(file),
'platforms': platforms,
'size': file.size_bytes,
'url': self.get_download_url(platform=platform),
'url': self.get_download_url(file),
}
)
return build_list

View File

@ -28,6 +28,7 @@ urlpatterns = [
path('search/', public.SearchView.as_view(), name='search'),
path('tag/<slug:tag_slug>/', public.SearchView.as_view(), name='by-tag'),
path('team/<slug:team_slug>/', public.SearchView.as_view(), name='by-team'),
path('download/<filehash>/<filename>', public.file_download, name='download'),
re_path(
rf'^(?P<type_slug>{EXTENSION_SLUGS_PATH})/',
include(
@ -91,11 +92,6 @@ urlpatterns = [
public.extension_version_download,
name='version-download',
),
path(
'<slug:slug>/<version>/<platform>/download/<filename>',
public.extension_version_platform_download,
name='version-platform-download',
),
path('<slug:slug>/versions/', manage.VersionsView.as_view(), name='versions'),
],
),

View File

@ -93,7 +93,7 @@ class ListedExtensionsSerializer(serializers.ModelSerializer):
'archive_size': file.size_bytes,
'archive_url': self.request.build_absolute_uri(
matching_version.get_download_url(
platform=self.platform,
file,
append_repository_and_compatibility=False,
)
),

View File

@ -4,21 +4,19 @@ import logging
from django.contrib.auth import get_user_model
from django.db import connection
from django.db.models import Count, Q
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect
from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView, ListView
from extensions.models import Extension, Version, Tag
from constants.base import (
EXTENSION_TYPE_SLUGS,
EXTENSION_TYPE_PLURAL,
EXTENSION_TYPE_CHOICES,
)
from stats.models import ExtensionView
from extensions.models import Extension, Version, Tag
from files.models import File
from stats.models import ExtensionDownload, ExtensionView, VersionDownload
import ratings.models
from stats.models import ExtensionDownload, VersionDownload
import teams.models
User = get_user_model()
@ -53,14 +51,16 @@ class HomeView(ListedExtensionsView):
def extension_version_download(request, type_slug, slug, version, filename):
"""A backward-compatible shortcut for the method below.
"""A backward-compatible url for downloads.
No platform is specified, assuming only a single file for a given version.
Assuming only a single file for a given version.
"""
return extension_version_platform_download(request, type_slug, slug, version, None, filename)
extension_version = get_object_or_404(Version, extension__slug=slug, version=version)
file = extension_version.files.first()
return file_download(request, file.hash, filename)
def extension_version_platform_download(request, type_slug, slug, version, platform, filename):
def file_download(request, filehash, filename):
"""Download an extension version and count downloads.
This method processes urls constructed by Version.get_download_list.
@ -70,13 +70,13 @@ def extension_version_platform_download(request, type_slug, slug, version, platf
drag&drop.
Also see $arg_filename usage in playbooks/templates/nginx/http.conf
"""
extension_version = get_object_or_404(Version, extension__slug=slug, version=version)
# TODO check file status
file = get_object_or_404(File, hash=filehash, version__isnull=False)
extension_version = file.version.first()
ExtensionDownload.create_from_request(request, object_id=extension_version.extension_id)
VersionDownload.create_from_request(request, object_id=extension_version.pk)
if file := extension_version.get_file_for_platform(platform):
url = file.source.url
return redirect(f'{url}?filename={filename}')
raise Http404()
url = file.source.url
return redirect(f'{url}?filename={filename}')
class SearchView(ListedExtensionsView):

View File

@ -82,7 +82,7 @@ class TestTasks(TestCase):
self.assertEqual(response.status_code, 200)
response = self.client.get(version.extension.get_versions_url())
self.assertEqual(response.status_code, 200)
response = self.client.get(version.get_download_url())
response = self.client.get(version.get_download_url(version.files.first()))
self.assertEqual(response.status_code, 302)
self.assertEqual(
response['Location'],