API: filter extension versions by blender_version parameter #86

Merged
Oleg-Komarov merged 2 commits from api-filter-blender-version into main 2024-04-22 15:24:06 +02:00
Showing only changes of commit 3ec5044a98 - Show all commits

View File

@ -42,38 +42,51 @@ class ListedExtensionsSerializer(serializers.ModelSerializer):
self.fail('invalid_version') self.fail('invalid_version')
def to_representation(self, instance): def to_representation(self, instance):
blender_version_min = instance.latest_version.blender_version_min matching_version = None
blender_version_max = instance.latest_version.blender_version_max # avoid triggering additional db queries, reuse the prefetched queryset
versions = [
# TODO: get the latest valid version v
# For now we skip the extension if the latest version is not in a valid range. for v in instance.versions.all()
if self.blender_version and not is_in_version_range( if v.file and v.file.status in instance.valid_file_statuses
self.blender_version, blender_version_min, blender_version_max ]
if not versions:
return None
versions = sorted(versions, key=lambda v: v.date_created, reverse=True)
if self.blender_version:
for v in versions:
if is_in_version_range(
self.blender_version,
v.blender_version_min,
v.blender_version_max,
): ):
return {} matching_version = v
break
else:
# same as latest_version, but without triggering a new queryset
matching_version = versions[0]
if not matching_version:
return None
data = { data = {
'id': instance.extension_id, 'id': instance.extension_id,
'schema_version': instance.latest_version.schema_version, 'schema_version': matching_version.schema_version,
'name': instance.name, 'name': instance.name,
'version': instance.latest_version.version, 'version': matching_version.version,
'tagline': instance.latest_version.tagline, 'tagline': matching_version.tagline,
'archive_hash': instance.latest_version.file.original_hash, 'archive_hash': matching_version.file.original_hash,
'archive_size': instance.latest_version.file.size_bytes, 'archive_size': matching_version.file.size_bytes,
'archive_url': self.request.build_absolute_uri(instance.latest_version.download_url), 'archive_url': self.request.build_absolute_uri(matching_version.download_url),
'type': EXTENSION_TYPE_SLUGS_SINGULAR.get(instance.type), 'type': EXTENSION_TYPE_SLUGS_SINGULAR.get(instance.type),
'blender_version_min': instance.latest_version.blender_version_min, 'blender_version_min': matching_version.blender_version_min,
'blender_version_max': instance.latest_version.blender_version_max, 'blender_version_max': matching_version.blender_version_max,
'website': self.request.build_absolute_uri(instance.get_absolute_url()), 'website': self.request.build_absolute_uri(instance.get_absolute_url()),
'maintainer': str(instance.authors.first()), # avoid triggering additional db queries, reuse the prefetched queryset
'license': [ 'maintainer': str(instance.authors.all()[0]),
license_iter.slug for license_iter in instance.latest_version.licenses.all() 'license': [license_iter.slug for license_iter in matching_version.licenses.all()],
], 'permissions': [permission.slug for permission in matching_version.permissions.all()],
'permissions': [
permission.slug for permission in instance.latest_version.permissions.all()
],
# TODO: handle copyright # TODO: handle copyright
'tags': [str(tag) for tag in instance.latest_version.tags.all()], 'tags': [str(tag) for tag in matching_version.tags.all()],
} }
return clean_json_dictionary_from_optional_fields(data) return clean_json_dictionary_from_optional_fields(data)
@ -93,10 +106,18 @@ class ExtensionsAPIView(APIView):
) )
def get(self, request): def get(self, request):
blender_version = request.GET.get('blender_version') blender_version = request.GET.get('blender_version')
qs = Extension.objects.listed.prefetch_related(
'authors',
'versions',
'versions__file',
'versions__licenses',
'versions__permissions',
'versions__tags',
).all()
serializer = self.serializer_class( serializer = self.serializer_class(
Extension.objects.listed, blender_version=blender_version, request=request, many=True qs, blender_version=blender_version, request=request, many=True
) )
data = serializer.data data = [e for e in serializer.data if e is not None]
return Response( return Response(
{ {
# TODO implement extension blocking by moderators # TODO implement extension blocking by moderators