def _create_or_update_task( ctask, user, competition, chain, index, text, comment): edit = bool(ctask.task_id) if not edit: content = MathContent(text=text) content.save() task = Task(content=content, author=user, hidden=True) comment = MathContent(text=comment) comment.save() ctask.comment = comment else: task = ctask.task task.content.text = text task.content.save() ctask.comment.text = comment ctask.comment.save() update_ctask_task(task, competition, chain, index + 1, commit=True) if not edit: if competition.automatic_task_tags: add_tags(task, competition.automatic_task_tags) if competition.admin_group: ObjectPermission.objects.create(content_object=task, group=competition.admin_group, permission_type=VIEW) ObjectPermission.objects.create(content_object=task, group=competition.admin_group, permission_type=EDIT) ctask.task = task
def create_tasks_from_json(description): """ Given a list of Task description dictionaries, create Task instances, together with other related objects. Supported special data: _content (string) - the text of the task, MathContent text _folder_id (int) - ID of the folder where to add the task _folder_position (int) - position in that folder _tags (string) - a comma-separated list of tags _difficulty (int) - difficulty rating to be assigned by the author _permissions (dict {"permission type ID": [list of group IDs]}) - group permission to automatically assign. - (ID is a string because in JSON keys must be strings) All other elements with an underscore are ignored. Params: description (list): list of dict object, describing the tasks Returns: A list of the new Task objects. If an exception is thrown in the middle of the process, the exception is caputed, the message changed, and raised again. """ # Approx. task_fields = set(Task._meta.get_all_field_names()) task_fields |= set(x + '_id' for x in task_fields) created_objects = [] created_tasks = [] message_list = [] # List of objects to create folder_tasks = [] object_permissions = [] try: for k, desc in enumerate(description): message_list.append('Creating {}. task...'.format(k + 1)) # First, prepare data to be able to create Task. # --- math content --- math_content = MathContent() math_content.text = desc['_content'] message_list.append(desc['_content']) math_content.save() created_objects.append(math_content) # Second, create Task. task = Task() task.content = math_content for key, value in desc.iteritems(): if key[0] != '_' and key in task_fields: setattr(task, key, value) task.save() created_objects.append(task) created_tasks.append(task) # Third, save other data. # --- tags --- tags = desc.get('_tags', '') set_tags(task, tags) # --- difficulty --- difficulty = desc.get('_difficulty') if difficulty: task.difficulty_rating.update(task.author, int(difficulty)) # --- folder ids --- folder_id = desc.get('_folder_id') if folder_id is not None: folder_tasks.append(FolderTask( folder_id=folder_id, task=task, position=desc.get('_folder_position', 0))) # --- group permissions --- for perm, group_ids in desc.get('_permissions', {}).iteritems(): for group_id in group_ids: object_permissions.append(ObjectPermission( content_object=task, group_id=group_id, permission_type=perm)) FolderTask.objects.bulk_create(folder_tasks) ObjectPermission.objects.bulk_create(object_permissions) except Exception as e: # This should remove all dependend objects. for obj in created_objects: obj.delete() message_list.append("Reverting changes...") message = "\n".join(message_list) + "\n\n" + traceback.format_exc() raise type(e)(message) finally: # SPEED: Don't invalidate everything. invalidate_cache_for_folders(Folder.objects.all()) return created_tasks