def destroy(self, request, pk=None):
        instance = self.get_object()
        program = instance.program
        parent = instance.parent

        role = request.user.tola_user.program_role(program.id)
        if request.user.is_anonymous or role != 'high':
            return HttpResponseRedirect('/')

        try:
            with transaction.atomic():
                self.perform_destroy(instance)

                levels_to_shift = Level.objects \
                    .filter(program=program, parent=parent) \
                    .order_by('customsort')
                for i, s_level in enumerate(levels_to_shift):
                    s_level.customsort = i + 1
                    s_level.save()

                all_levels = Level.objects.filter(program=instance.program)

        except Exception as e:
            logger.error(e)
            return JsonResponse(
                {'message': _('Your request could not be processed.')},
                status=400)

        return Response(LevelSerializer(all_levels, many=True).data)
def insert_new_level(request):
    level_data = copy.copy(request.data)
    program = Program.objects.get(id=request.data['program'])

    role = request.user.tola_user.program_role(program.id)
    if request.user.is_anonymous or role != 'high':
        return HttpResponseRedirect('/')

    # Update new Level data in preparation for saving
    if request.data['parent'] == "root":
        parent = None
    else:
        parent = Level.objects.get(id=request.data['parent'])
    level_data['parent'] = parent
    level_data['program'] = program
    if 'ontology' in request.data:
        del level_data['ontology']
    del level_data['level_depth']

    # First update the customsort values of all Levels that getting pushed down by the new Level.
    # No need to do it if the top tier level is being saved
    if request.data['parent'] != "root":
        levels_to_shift = Level.objects\
            .filter(program=program, parent_id=parent.id, customsort__gte=request.data['customsort'])\
            .order_by('-customsort')
        for s_level in levels_to_shift:
            s_level.customsort += 1
            s_level.save()

    new_level = Level(**level_data)

    try:
        new_level.full_clean()
    except ValidationError as e:
        return Response(e.message_dict, status=400)

    # Now the new level can be saved
    new_level.save()

    # Return all Levels for the program. There shouldn't be so much that it slows things down much.
    # Also return the newly created Level.
    all_data = LevelSerializer(Level.objects.filter(program=program),
                               many=True).data
    return Response({
        'all_data': all_data,
        'new_level': LevelSerializer(new_level).data
    })
    def get(self, request, *args, **kwargs):
        # TODO:  put in a try block
        program = Program.objects.prefetch_related('level_tiers').get(
            pk=int(self.kwargs['program_id']))
        role = request.user.tola_user.program_role(program.id)

        if not role or (role in ['low', 'medium']
                        and program.level_tiers.count() == 0):
            return HttpResponseRedirect('/')

        tiers = LevelTier.objects.filter(program=program)
        try:
            custom_tiers = LevelTierTemplate.objects.get(program=program)
        except LevelTierTemplate.DoesNotExist:
            custom_tiers = None
        levels = Level.objects.filter(program=program)
        # All indicators associated with the program should be passed to the front-end, not just the ones
        # associated with the rf levels.  The front-end uses the overall count to determine whether
        # the program name in the header should be plain text or a link.
        indicators = Indicator.objects.filter(program=program,
                                              deleted__isnull=True)

        translated_templates = json.dumps(LevelTier.get_templates(),
                                          cls=LazyEncoder)
        old_lang = translation.get_language()
        translation.activate('en')
        untranslated_templates = json.dumps(LevelTier.get_templates(),
                                            cls=LazyEncoder)
        translation.activate(old_lang)
        js_context = {
            'program':
            ResultsFrameworkProgramSerializer(program).data,
            'levels':
            LevelSerializer(levels, many=True).data,
            'indicators':
            IndicatorSerializerMinimal(indicators, many=True).data,
            'levelTiers':
            LevelTierSerializer(tiers, many=True).data,
            'tierTemplates':
            translated_templates,
            'englishTemplates':
            untranslated_templates,
            'customTemplates':
            LevelTierTemplateSerializer(custom_tiers).data,
            'programObjectives':
            ProgramObjectiveSerializer(program.objective_set.all(),
                                       many=True).data,
            'accessLevel':
            role,
            'usingResultsFramework':
            program.results_framework,
        }

        context_data = {
            'program': program,
            'indicator_count': indicators.count(),
            'js_context': js_context,
        }
        return render(request, self.template_name, context_data)