diff --git a/docs/user/api/v3.rst b/docs/user/api/v3.rst index e79e4cd3225..7bea577c036 100644 --- a/docs/user/api/v3.rst +++ b/docs/user/api/v3.rst @@ -1855,12 +1855,12 @@ Remote repository listing .. code-tab:: bash - $ curl -H "Authorization: Token " https://readthedocs.org/api/v3/remote/repositories/?expand=projects,remote_organization + $ curl -H "Authorization: Token " https://readthedocs.org/api/v3/remote/repositories/?expand=remote_organization .. code-tab:: python import requests - URL = 'https://readthedocs.org/api/v3/remote/repositories/?expand=projects,remote_organization' + URL = 'https://readthedocs.org/api/v3/remote/repositories/?expand=remote_organization' TOKEN = '' HEADERS = {'Authorization': f'token {TOKEN}'} response = requests.get(URL, headers=HEADERS) @@ -1872,7 +1872,7 @@ Remote repository listing { "count": 20, - "next": "api/v3/remote/repositories/?expand=projects,remote_organization&limit=10&offset=10", + "next": "api/v3/remote/repositories/?expand=remote_organization&limit=10&offset=10", "previous": null, "results": [ { @@ -1886,7 +1886,7 @@ Remote repository listing "url": "https://github.com/organization", "vcs_provider": "github" }, - "project": [{ + "projects": [{ "id": 12345, "name": "project", "slug": "project", @@ -1957,7 +1957,7 @@ Remote repository listing :query string vcs_provider: return remote repositories for specific vcs provider (``github``, ``gitlab`` or ``bitbucket``) :query string organization: return remote repositories for specific remote organization (using remote organization ``slug``) :query string expand: Add additional fields in the response. - Allowed values are ``projects`` and ``remote_organization``. + Allowed values are: ``remote_organization``. Multiple fields can be passed separated by commas. :requestheader Authorization: token to authenticate. diff --git a/readthedocs/api/v3/serializers.py b/readthedocs/api/v3/serializers.py index 7f4cef9174c..b933f3dd09a 100644 --- a/readthedocs/api/v3/serializers.py +++ b/readthedocs/api/v3/serializers.py @@ -1249,6 +1249,7 @@ class Meta: class RemoteRepositorySerializer(FlexFieldsModelSerializer): admin = serializers.SerializerMethodField("is_admin") + projects = serializers.SerializerMethodField() class Meta: model = RemoteRepository @@ -1268,6 +1269,7 @@ class Meta: "default_branch", "created", "modified", + "projects", ] read_only_fields = fields expandable_fields = { @@ -1275,7 +1277,6 @@ class Meta: RemoteOrganizationSerializer, {"source": "organization"}, ), - "projects": (ProjectSerializer, {"many": True}), } def is_admin(self, obj): @@ -1288,3 +1289,12 @@ def is_admin(self, obj): return obj.remote_repository_relations.filter( user=request.user, admin=True ).exists() + + def get_projects(self, obj): + request = self.context["request"] + projects = ( + Project.objects.public(user=request.user) + .filter(remote_repository=obj) + .prefetch_related("users") + ) + return ProjectSerializer(projects, many=True).data diff --git a/readthedocs/api/v3/tests/test_remoterepositories.py b/readthedocs/api/v3/tests/test_remoterepositories.py index dfab056b100..94862a7336e 100644 --- a/readthedocs/api/v3/tests/test_remoterepositories.py +++ b/readthedocs/api/v3/tests/test_remoterepositories.py @@ -1,7 +1,6 @@ -from django.urls import reverse - -from allauth.socialaccount.models import SocialAccount import django_dynamic_fixture as fixture +from allauth.socialaccount.models import SocialAccount +from django.urls import reverse from readthedocs.oauth.constants import GITHUB from readthedocs.oauth.models import ( @@ -11,6 +10,7 @@ RemoteRepositoryRelation, ) from readthedocs.projects.constants import REPO_TYPE_GIT + from .mixins import APIEndpointMixin @@ -65,7 +65,7 @@ def setUp(self): def test_remote_repository_list(self): url = reverse("remoterepositories-list") - data = {"expand": ("projects," "remote_organization")} + data = {"expand": ["remote_organization"]} self.client.logout() response = self.client.get(url, data) @@ -84,7 +84,7 @@ def test_remote_repository_list_name_filter(self): self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token.key}") response = self.client.get( reverse("remoterepositories-list"), - {"expand": ("projects," "remote_organization"), "name": "proj"}, + {"expand": ["remote_organization"], "name": "proj"}, ) self.assertEqual(response.status_code, 200) @@ -100,7 +100,7 @@ def test_remote_repository_list_full_name_filter(self): self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token.key}") response = self.client.get( reverse("remoterepositories-list"), - {"expand": ("projects," "remote_organization"), "full_name": "proj"}, + {"expand": ["remote_organization"], "full_name": "proj"}, ) self.assertEqual(response.status_code, 200) diff --git a/readthedocs/api/v3/views.py b/readthedocs/api/v3/views.py index b654054ed8e..5376a081f4c 100644 --- a/readthedocs/api/v3/views.py +++ b/readthedocs/api/v3/views.py @@ -594,7 +594,7 @@ class RemoteRepositoryViewSet( serializer_class = RemoteRepositorySerializer filterset_class = RemoteRepositoryFilter permission_classes = (IsAuthenticated,) - permit_list_expands = ["remote_organization", "projects"] + permit_list_expands = ["remote_organization"] def get_queryset(self): queryset = ( @@ -615,9 +615,6 @@ def get_queryset(self): if is_expanded(self.request, "remote_organization"): queryset = queryset.select_related("organization") - if is_expanded(self.request, "projects"): - queryset = queryset.prefetch_related("projects__users") - return queryset.order_by("organization__name", "full_name").distinct()