18
18
from rest_framework_extensions .mixins import NestedViewSetMixin
19
19
20
20
from readthedocs .builds .models import Build , Version
21
- from readthedocs .core .utils import trigger_build
21
+ from readthedocs .core .utils import trigger_build , trigger_initial_build
22
22
from readthedocs .projects .models import Project
23
+ from readthedocs .projects .signals import project_import
24
+
23
25
24
26
from .filters import BuildFilter , ProjectFilter , VersionFilter
25
27
from .mixins import ProjectQuerySetMixin
29
31
BuildCreateSerializer ,
30
32
BuildSerializer ,
31
33
ProjectSerializer ,
34
+ ProjectCreateSerializer ,
32
35
VersionSerializer ,
33
36
VersionUpdateSerializer ,
34
37
)
@@ -63,7 +66,7 @@ class APIv3Settings:
63
66
64
67
65
68
class ProjectsViewSet (APIv3Settings , NestedViewSetMixin , ProjectQuerySetMixin ,
66
- FlexFieldsMixin , ReadOnlyModelViewSet ):
69
+ FlexFieldsMixin , CreateModelMixin , ReadOnlyModelViewSet ):
67
70
68
71
# Markdown docstring is automatically rendered by BrowsableAPIRenderer.
69
72
@@ -111,14 +114,13 @@ class ProjectsViewSet(APIv3Settings, NestedViewSetMixin, ProjectQuerySetMixin,
111
114
* Subprojects of a project: ``/api/v3/projects/{project_slug}/subprojects/``
112
115
* Superproject of a project: ``/api/v3/projects/{project_slug}/superproject/``
113
116
114
- Go to [https://docs.readthedocs.io/en/stable/ api/v3.html](https://docs.readthedocs.io/en/stable /api/v3.html)
117
+ Go to [https://docs.readthedocs.io/page/ api/v3.html](https://docs.readthedocs.io/page /api/v3.html)
115
118
for a complete documentation of the APIv3.
116
119
""" # noqa
117
120
118
121
model = Project
119
122
lookup_field = 'slug'
120
123
lookup_url_kwarg = 'project_slug'
121
- serializer_class = ProjectSerializer
122
124
filterset_class = ProjectFilter
123
125
queryset = Project .objects .all ()
124
126
permit_list_expands = [
@@ -127,6 +129,20 @@ class ProjectsViewSet(APIv3Settings, NestedViewSetMixin, ProjectQuerySetMixin,
127
129
'active_versions.last_build.config' ,
128
130
]
129
131
132
+ def get_serializer_class (self ):
133
+ """
134
+ Return correct serializer depending on the action.
135
+
136
+ For GET it returns a serializer with many fields and on PUT/PATCH/POST,
137
+ it return a serializer to validate just a few fields.
138
+ """
139
+ if self .action in ('list' , 'retrieve' ):
140
+ return ProjectSerializer
141
+ elif self .action in ('create' ,):
142
+ return ProjectCreateSerializer
143
+ # elif self.action in ('update', 'partial_update'):
144
+ # return ProjectUpdateSerializer
145
+
130
146
def get_queryset (self ):
131
147
# Allow hitting ``/api/v3/projects/`` to list their own projects
132
148
if self .basename == 'projects' and self .action == 'list' :
@@ -162,6 +178,33 @@ def get_view_description(self, *args, **kwargs): # pylint: disable=arguments-di
162
178
return mark_safe (description .format (project_slug = project .slug ))
163
179
return description
164
180
181
+ def create (self , request , * args , ** kwargs ):
182
+ """
183
+ Override method to importing a Project.
184
+
185
+ * Save the Project object
186
+ * Assign the user from the request as owner
187
+ * Sent project_import signal
188
+ * Trigger an initial Build
189
+ """
190
+ serializer = self .get_serializer (data = request .data )
191
+ serializer .is_valid (raise_exception = True )
192
+ project = serializer .save ()
193
+ headers = self .get_success_headers (serializer .data )
194
+
195
+ # TODO: these lines need to be adapted for Corporate
196
+ project .users .add (request .user )
197
+ project_import .send (sender = project , request = request )
198
+ trigger_initial_build (project , request .user )
199
+
200
+ # Full render Project
201
+ serializer = ProjectSerializer (instance = project )
202
+ return Response (
203
+ serializer .data ,
204
+ status = status .HTTP_201_CREATED ,
205
+ headers = headers ,
206
+ )
207
+
165
208
@action (detail = True , methods = ['get' ])
166
209
def superproject (self , request , project_slug ):
167
210
"""Return the superproject of a ``Project``."""
0 commit comments