See #432: added admin API endpoints to retrieve and delete tags

This commit is contained in:
Eliot Berriot 2019-07-24 10:24:30 +02:00
parent c885c10be1
commit 13f36beec3
No known key found for this signature in database
GPG Key ID: DD6965E2476E5C27
6 changed files with 127 additions and 1 deletions

View File

@ -13,6 +13,7 @@ from funkwhale_api.federation import utils as federation_utils
from funkwhale_api.moderation import models as moderation_models from funkwhale_api.moderation import models as moderation_models
from funkwhale_api.music import models as music_models from funkwhale_api.music import models as music_models
from funkwhale_api.users import models as users_models from funkwhale_api.users import models as users_models
from funkwhale_api.tags import models as tags_models
class ActorField(forms.CharField): class ActorField(forms.CharField):
@ -340,3 +341,11 @@ class ManageInstancePolicyFilterSet(filters.FilterSet):
"silence_notifications", "silence_notifications",
"reject_media", "reject_media",
] ]
class ManageTagFilterSet(filters.FilterSet):
q = fields.SearchFilter(search_fields=["name"])
class Meta:
model = tags_models.Tag
fields = ["q"]

View File

@ -10,6 +10,7 @@ from funkwhale_api.federation import tasks as federation_tasks
from funkwhale_api.moderation import models as moderation_models from funkwhale_api.moderation import models as moderation_models
from funkwhale_api.music import models as music_models from funkwhale_api.music import models as music_models
from funkwhale_api.music import serializers as music_serializers from funkwhale_api.music import serializers as music_serializers
from funkwhale_api.tags import models as tags_models
from funkwhale_api.users import models as users_models from funkwhale_api.users import models as users_models
from . import filters from . import filters
@ -564,3 +565,30 @@ class ManageUploadSerializer(serializers.ModelSerializer):
"track", "track",
"library", "library",
) )
class ManageTagSerializer(ManageBaseAlbumSerializer):
tracks_count = serializers.SerializerMethodField()
albums_count = serializers.SerializerMethodField()
artists_count = serializers.SerializerMethodField()
class Meta:
model = tags_models.Tag
fields = [
"id",
"name",
"creation_date",
"tracks_count",
"albums_count",
"artists_count",
]
def get_tracks_count(self, obj):
return getattr(obj, "_tracks_count", None)
def get_albums_count(self, obj):
return getattr(obj, "_albums_count", None)
def get_artists_count(self, obj):
return getattr(obj, "_artists_count", None)

View File

@ -24,6 +24,7 @@ users_router.register(r"invitations", views.ManageInvitationViewSet, "invitation
other_router = routers.OptionalSlashRouter() other_router = routers.OptionalSlashRouter()
other_router.register(r"accounts", views.ManageActorViewSet, "accounts") other_router.register(r"accounts", views.ManageActorViewSet, "accounts")
other_router.register(r"tags", views.ManageTagViewSet, "tags")
urlpatterns = [ urlpatterns = [
url( url(

View File

@ -2,7 +2,7 @@ from rest_framework import mixins, response, viewsets
from rest_framework import decorators as rest_decorators from rest_framework import decorators as rest_decorators
from django.db.models import Count, Prefetch, Q, Sum, OuterRef, Subquery from django.db.models import Count, Prefetch, Q, Sum, OuterRef, Subquery
from django.db.models.functions import Coalesce from django.db.models.functions import Coalesce, Length
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from funkwhale_api.common import models as common_models from funkwhale_api.common import models as common_models
@ -14,6 +14,7 @@ from funkwhale_api.history import models as history_models
from funkwhale_api.music import models as music_models from funkwhale_api.music import models as music_models
from funkwhale_api.moderation import models as moderation_models from funkwhale_api.moderation import models as moderation_models
from funkwhale_api.playlists import models as playlists_models from funkwhale_api.playlists import models as playlists_models
from funkwhale_api.tags import models as tags_models
from funkwhale_api.users import models as users_models from funkwhale_api.users import models as users_models
@ -452,3 +453,43 @@ class ManageInstancePolicyViewSet(
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(actor=self.request.user.actor) serializer.save(actor=self.request.user.actor)
class ManageTagViewSet(
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
mixins.CreateModelMixin,
viewsets.GenericViewSet,
):
lookup_field = "name"
queryset = (
tags_models.Tag.objects.all()
.order_by("-creation_date")
.annotate(items_count=Count("tagged_items"))
.annotate(length=Length("name"))
)
serializer_class = serializers.ManageTagSerializer
filterset_class = filters.ManageTagFilterSet
required_scope = "instance:libraries"
ordering_fields = ["id", "creation_date", "name", "items_count", "length"]
def get_queryset(self):
queryset = super().get_queryset()
from django.contrib.contenttypes.models import ContentType
album_ct = ContentType.objects.get_for_model(music_models.Album)
track_ct = ContentType.objects.get_for_model(music_models.Track)
artist_ct = ContentType.objects.get_for_model(music_models.Artist)
queryset = queryset.annotate(
_albums_count=Count(
"tagged_items", filter=Q(tagged_items__content_type=album_ct)
),
_tracks_count=Count(
"tagged_items", filter=Q(tagged_items__content_type=track_ct)
),
_artists_count=Count(
"tagged_items", filter=Q(tagged_items__content_type=artist_ct)
),
)
return queryset

View File

@ -496,3 +496,22 @@ def test_action_serializer_delete(factory, serializer_class, factories):
s.handle_delete(objects[0].__class__.objects.all()) s.handle_delete(objects[0].__class__.objects.all())
assert objects[0].__class__.objects.count() == 0 assert objects[0].__class__.objects.count() == 0
def test_manage_tag_serializer(factories):
tag = factories["tags.Tag"]()
setattr(tag, "_tracks_count", 42)
setattr(tag, "_albums_count", 54)
setattr(tag, "_artists_count", 66)
expected = {
"id": tag.id,
"name": tag.name,
"creation_date": tag.creation_date.isoformat().split("+")[0] + "Z",
"tracks_count": 42,
"albums_count": 54,
"artists_count": 66,
}
s = serializers.ManageTagSerializer(tag)
assert s.data == expected

View File

@ -377,3 +377,31 @@ def test_upload_delete(factories, superuser_api_client):
response = superuser_api_client.delete(url) response = superuser_api_client.delete(url)
assert response.status_code == 204 assert response.status_code == 204
def test_tag_detail(factories, superuser_api_client):
tag = factories["tags.Tag"]()
url = reverse("api:v1:manage:tags-detail", kwargs={"name": tag.name})
response = superuser_api_client.get(url)
assert response.status_code == 200
assert response.data["name"] == tag.name
def test_tag_list(factories, superuser_api_client, settings):
tag = factories["tags.Tag"]()
url = reverse("api:v1:manage:tags-list")
response = superuser_api_client.get(url)
assert response.status_code == 200
assert response.data["count"] == 1
assert response.data["results"][0]["name"] == tag.name
def test_tag_delete(factories, superuser_api_client):
tag = factories["tags.Tag"]()
url = reverse("api:v1:manage:tags-detail", kwargs={"name": tag.name})
response = superuser_api_client.delete(url)
assert response.status_code == 204