def new(request, folder_id=None): # Analogous to task.models.new if folder_id: folder = get_object_or_404(Folder, id=folder_id) edit = True old_parent_id = folder.parent_id else: folder = old_parent_id = None edit = False data = {} initial_parent_id = None if edit: if not folder.editable: return response.FORBIDDEN permissions = folder.get_user_permissions(request.user) if EDIT not in permissions: return response.FORBIDDEN if EDIT_PERMISSIONS in permissions: data['can_edit_permissions'] = True data['content_type'] = ContentType.objects.get_for_model(Folder) data['children'] = children = list(Folder.objects \ .for_user(request.user, VIEW) \ .filter(parent=folder).order_by('parent_index').distinct()) data['has_subfolders_strict'] = Folder.objects \ .filter(parent_id=folder_id).exists() else: referrer = get_referrer_path(request) if referrer and referrer.startswith('/folder/'): try: initial_parent_id = int(referrer[8:referrer.find('/', 8)]) except: pass if request.method == 'POST': folder_form = FolderForm(request.POST, instance=folder, user=request.user) if folder_form.is_valid(): folder = folder_form.save(commit=False) # TODO: Make a util function for creating Folder instances, to be # able to create tests easier. # If user can't edit short name, copy full name. if 'short_name' not in folder_form.fields: folder.short_name = folder.name if not edit: folder.author = request.user else: for x in children: parent_index = request.POST.get('child-{}'.format(x.id)) parent_index = int(parent_index) if parent_index is not None \ and x.parent_index != parent_index: x.parent_index = parent_index x.save() # Update order... children.sort(key=lambda x: x.parent_index) # If editing, refresh immediately before saving. # Do not call folder_form.save_m2m()! folder._no_save = True set_tags(folder, folder_form.cleaned_data['tags']) folder.save() if not edit: # If new, first save folder (and define ID), and then save tags. set_tags(folder, folder_form.cleaned_data['tags']) # Refresh Folder cache. if old_parent_id != folder.parent_id: # The only folders that have to be refreshed are those in # the folder's subtree, together with folder itself. descendant_ids = get_folder_descendant_ids(folder.id) descendant_ids.append(folder.id) # refresh_path_cache also requires ancestors. Following code # works, because you can't move a folder into its child folder. descendant_ids.extend([int(x) for x in folder.parent.cache_ancestor_ids.split(',') if x]) descendant_ids.append(folder.parent_id) refresh_path_cache(Folder.objects.filter(id__in=descendant_ids)) if not edit: return ('/folder/{}/edit/'.format(folder.id), ) # return HttpResponseRedirect(folder.get_absolute_url()) else: folder_form = FolderForm(instance=folder, user=request.user, initial_parent_id=initial_parent_id) # If parent given and acceptable, show menu. (new mode) initial_parent = getattr(folder_form, 'initial_parent', None) if initial_parent: data.update(prepare_folder_menu([initial_parent], request.user)) if edit: data.update(prepare_folder_menu([folder], request.user)) data['folder'] = folder data['form'] = folder_form data['edit'] = edit if request.user.has_perm('folder.advanced_create'): data['advanced_create_permission'] = True return data
def test_get_folder_descendant_ids(self): self.assertEqual(sorted(get_folder_descendant_ids(1)), [2, 3, 4]) self.assertEqual(sorted(get_folder_descendant_ids(2)), [3, 4]) self.assertEqual(sorted(get_folder_descendant_ids(3)), []) self.assertEqual(sorted(get_folder_descendant_ids(4)), [])