@@ -85,6 +85,42 @@ def _create_departments(self, departments: List[str]) -> models.QuerySet: # noq
8585
8686 return Department .objects .filter (name__in = departments ).all ()
8787
88+ def _get_or_create_departments (
89+ self ,
90+ department_names : list [str ],
91+ * ,
92+ create_if_missing : bool ,
93+ ) -> models .QuerySet :
94+ """
95+ Retrieves or creates Department objects based on the provided names.
96+
97+ Args:
98+ department_names (List[str]): List of department names.
99+ create_if_missing (bool): If True, creates departments that don't exist.
100+ If False, exits with an error if any departments don't exist.
101+
102+ Returns:
103+ models.QuerySet: Query set containing all of the departments specified
104+ in the list of department names.
105+ """
106+ if not department_names :
107+ self ._department_must_be_defined_error ()
108+
109+ existing_depts = Department .objects .filter (name__in = department_names )
110+ existing_names = {dept .name for dept in existing_depts }
111+ missing_names = [
112+ name for name in department_names if name not in existing_names
113+ ]
114+
115+ if missing_names :
116+ if create_if_missing :
117+ for dept_name in missing_names :
118+ Department .objects .create (name = dept_name )
119+ else :
120+ self ._departments_do_not_exist_error ()
121+
122+ return Department .objects .filter (name__in = department_names )
123+
88124 def _department_must_be_defined_error (self ):
89125 """
90126 Outputs an error message indicating that departments must be
@@ -169,6 +205,121 @@ def _create_course_run(self, course, **kwargs):
169205 self .style .SUCCESS (f"Created course run { course_run .id } : { course_run } " )
170206 )
171207
208+ def _handle_program (self , add_depts : models .QuerySet , ** kwargs ):
209+ """Handle creation of a program."""
210+ self ._check_if_courseware_object_readable_id_exists (
211+ Program , kwargs ["courseware_id" ]
212+ )
213+
214+ new_program = Program .objects .create (
215+ readable_id = kwargs ["courseware_id" ],
216+ title = kwargs ["title" ],
217+ live = kwargs ["live" ],
218+ )
219+
220+ self ._add_departments_to_courseware_object (new_program , add_depts )
221+
222+ self ._successfully_created_courseware_object_message (new_program )
223+
224+ if kwargs ["related" ] is not None and len (kwargs ["related" ]) > 0 :
225+ for readable_id in kwargs ["related" ]:
226+ try :
227+ related_program = Program .objects .filter (
228+ readable_id = readable_id
229+ ).get ()
230+ new_program .add_related_program (related_program )
231+
232+ self .stdout .write (
233+ self .style .SUCCESS (f"Added relationship for { readable_id } ." )
234+ )
235+ except Exception : # noqa: BLE001, PERF203
236+ self .stderr .write (
237+ self .style .ERROR (
238+ f"Can't add relationship for { readable_id } : program not found."
239+ )
240+ )
241+
242+ self .stdout .write (
243+ self .style .SUCCESS (
244+ f"Added { len (new_program .related_programs )} program relationships."
245+ )
246+ )
247+
248+ def _handle_course (self , add_depts : models .QuerySet , ** kwargs ):
249+ """Handle creation of a course."""
250+ self ._check_if_courseware_object_readable_id_exists (
251+ Course , kwargs ["courseware_id" ]
252+ )
253+
254+ new_course = Course .objects .create (
255+ title = kwargs ["title" ],
256+ readable_id = kwargs ["courseware_id" ],
257+ live = kwargs ["live" ],
258+ )
259+
260+ self ._add_departments_to_courseware_object (new_course , add_depts )
261+
262+ self ._successfully_created_courseware_object_message (new_course )
263+
264+ if "create_run" in kwargs and kwargs ["create_run" ] is not None :
265+ self ._create_course_run (new_course , ** kwargs )
266+
267+ if kwargs ["live" ] or kwargs ["force" ]:
268+ if kwargs ["force" ]:
269+ self .stderr .write (
270+ self .style .ERROR (
271+ f"WARNING: creating a requirement for { new_course .readable_id } anyway since you specified --force. This will probably break the Django Admin until you set the course to Live."
272+ )
273+ )
274+
275+ new_req = None
276+
277+ if "program" in kwargs and kwargs ["program" ] is not None :
278+ try :
279+ program = Program .objects .filter (pk = kwargs ["program" ]).first ()
280+ except : # noqa: E722
281+ program = Program .objects .filter (readable_id = kwargs ["program" ]).first ()
282+
283+ self ._add_departments_to_courseware_object (program , add_depts )
284+
285+ if program is not None and kwargs ["required" ]:
286+ new_req = program .add_requirement (new_course )
287+ elif program is not None and kwargs ["elective" ]:
288+ new_req = program .add_elective (new_course )
289+
290+ if new_req is not None :
291+ self .stdout .write (
292+ self .style .SUCCESS (
293+ f"Added { new_course .readable_id } to { program .readable_id } 's { new_req .get_parent ().title } requirements."
294+ )
295+ )
296+ else :
297+ self .stdout .write (
298+ f"Live flag not specified for { new_course .readable_id } , ignoring any requirements flags"
299+ )
300+
301+ def _handle_courserun (self , ** kwargs ):
302+ """Handle creation of a course run."""
303+ if not Course .objects .filter (readable_id = kwargs ["courseware_id" ]).exists ():
304+ self .stderr .write (
305+ self .style .ERROR (
306+ f"Course with ID { kwargs ['courseware_id' ]} doesn't exist."
307+ )
308+ )
309+ exit (- 1 ) # noqa: PLR1722
310+
311+ if "create_run" not in kwargs or kwargs ["create_run" ] is None :
312+ self .stderr .write (
313+ self .style .ERROR (
314+ "You must specify the run tag with either --run-tag or --create-run when creating a course run."
315+ )
316+ )
317+ exit (- 1 ) # noqa: PLR1722
318+
319+ course = Course .objects .filter (readable_id = kwargs ["courseware_id" ]).get ()
320+
321+ self ._create_course_run (course , ** kwargs )
322+
172323 def add_arguments (self , parser ) -> None :
173324 parser .add_argument (
174325 "type" ,
@@ -297,7 +448,7 @@ def add_arguments(self, parser) -> None:
297448 action = "store_true" ,
298449 )
299450
300- def handle (self , * args , ** kwargs ): # pylint: disable=unused-argument # noqa: C901, PLR0915
451+ def handle (self , * _args , ** kwargs ):
301452 if not (
302453 kwargs ["force" ]
303454 or kwargs ["courseware_id" ].startswith ("course" )
@@ -310,134 +461,17 @@ def handle(self, *args, **kwargs): # pylint: disable=unused-argument # noqa: C
310461 )
311462 exit (- 1 ) # noqa: PLR1722
312463
313- if kwargs ["type" ] == "program" :
314- if kwargs ["depts" ] and len (kwargs ["depts" ]) > 0 :
315- add_depts = Department .objects .filter (name__in = kwargs ["depts" ]).all ()
316- else :
317- self ._department_must_be_defined_error ()
318-
319- if kwargs ["create_depts" ]:
320- add_depts = self ._create_departments (kwargs ["depts" ])
321- elif not add_depts :
322- self ._departments_do_not_exist_error ()
323-
324- self ._check_if_courseware_object_readable_id_exists (
325- Program , kwargs ["courseware_id" ]
326- )
327-
328- new_program = Program .objects .create (
329- readable_id = kwargs ["courseware_id" ],
330- title = kwargs ["title" ],
331- live = kwargs ["live" ],
464+ # Validate/create departments for programs and courses (not needed for courseruns)
465+ if kwargs ["type" ] in ["program" , "course" ]:
466+ add_depts = self ._get_or_create_departments (
467+ kwargs ["depts" ], create_if_missing = kwargs ["create_depts" ]
332468 )
333469
334- self ._add_departments_to_courseware_object (new_program , add_depts )
335-
336- self ._successfully_created_courseware_object_message (new_program )
337-
338- if kwargs ["related" ] is not None and len (kwargs ["related" ]) > 0 :
339- for readable_id in kwargs ["related" ]:
340- try :
341- related_program = Program .objects .filter (
342- readable_id = readable_id
343- ).get ()
344- new_program .add_related_program (related_program )
345-
346- self .stdout .write (
347- self .style .SUCCESS (f"Added relationship for { readable_id } ." )
348- )
349- except Exception : # noqa: BLE001, PERF203
350- self .stderr .write (
351- self .style .ERROR (
352- f"Can't add relationship for { readable_id } : program not found."
353- )
354- )
355-
356- self .stdout .write (
357- self .style .SUCCESS (
358- f"Added { len (new_program .related_programs )} program relationships."
359- )
360- )
470+ if kwargs ["type" ] == "program" :
471+ self ._handle_program (add_depts , ** kwargs )
361472 elif kwargs ["type" ] == "course" :
362- self ._check_if_courseware_object_readable_id_exists (
363- Course , kwargs ["courseware_id" ]
364- )
365-
366- new_course = Course .objects .create (
367- title = kwargs ["title" ],
368- readable_id = kwargs ["courseware_id" ],
369- live = kwargs ["live" ],
370- )
371-
372- if kwargs ["depts" ] and len (kwargs ["depts" ]) > 0 :
373- add_depts = Department .objects .filter (name__in = kwargs ["depts" ]).all ()
374- else :
375- self ._department_must_be_defined_error ()
376-
377- if kwargs ["create_depts" ]:
378- add_depts = self ._create_departments (kwargs ["depts" ])
379- if "add_depts" not in locals () or not add_depts :
380- self ._departments_do_not_exist_error ()
381-
382- self ._successfully_created_courseware_object_message (new_course )
383-
384- if "create_run" in kwargs and kwargs ["create_run" ] is not None :
385- self ._create_course_run (new_course , ** kwargs )
386-
387- if kwargs ["live" ] or kwargs ["force" ]:
388- if kwargs ["force" ]:
389- self .stderr .write (
390- self .style .ERROR (
391- f"WARNING: creating a requirement for { new_course .readable_id } anyway since you specified --force. This will probably break the Django Admin until you set the course to Live."
392- )
393- )
394-
395- new_req = None
396-
397- if "program" in kwargs and kwargs ["program" ] is not None :
398- try :
399- program = Program .objects .filter (pk = kwargs ["program" ]).first ()
400- except : # noqa: E722
401- program = Program .objects .filter (
402- readable_id = kwargs ["program" ]
403- ).first ()
404-
405- self ._add_departments_to_courseware_object (program , add_depts )
406-
407- if program is not None and kwargs ["required" ]:
408- new_req = program .add_requirement (new_course )
409- elif program is not None and kwargs ["elective" ]:
410- new_req = program .add_elective (new_course )
411-
412- if new_req is not None :
413- self .stdout .write (
414- self .style .SUCCESS (
415- f"Added { new_course .readable_id } to { program .readable_id } 's { new_req .get_parent ().title } requirements."
416- )
417- )
418- else :
419- self .stdout .write (
420- f"Live flag not specified for { new_course .readable_id } , ignoring any requirements flags"
421- )
473+ self ._handle_course (add_depts , ** kwargs )
422474 elif kwargs ["type" ] == "courserun" :
423- if not Course .objects .filter (readable_id = kwargs ["courseware_id" ]).exists ():
424- self .stderr .write (
425- self .style .ERROR (
426- f"Course with ID { kwargs ['courseware_id' ]} doesn't exist."
427- )
428- )
429- exit (- 1 ) # noqa: PLR1722
430-
431- if "create_run" not in kwargs or kwargs ["create_run" ] is None :
432- self .stderr .write (
433- self .style .ERROR (
434- "You must specify the run tag with either --run-tag or --create-run when creating a course run."
435- )
436- )
437- exit (- 1 ) # noqa: PLR1722
438-
439- course = Course .objects .filter (readable_id = kwargs ["courseware_id" ]).get ()
440-
441- self ._create_course_run (course , ** kwargs )
475+ self ._handle_courserun (** kwargs )
442476 else :
443477 self .stderr .write (self .style .ERROR (f"Not sure what { kwargs ['type' ]} is." ))
0 commit comments