Example #1
0
def manage_project_strings(request, slug=None):
    """View to manage the source strings of a project.

    This view is only accessible for projects that do not have a "Source repo". It allows
    admins to add new strings to a project in a batch, and then to edit, remove or comment on
    any strings.

    """
    if not request.user.has_perm('base.can_manage_project'):
        raise PermissionDenied

    try:
        project = Project.objects.get(slug=slug)
    except Project.DoesNotExist:
        raise Http404

    if project.data_source != 'database':
        return HttpResponseForbidden(
            'Project %s\'s strings come from a repository, managing strings is forbidden.'
            % project.name)

    entities = Entity.objects.filter(resource__project=project, obsolete=False)
    project_has_strings = entities.exists()
    formset = EntityFormSet(queryset=entities)

    if request.GET.get('format') == 'csv':
        # Return a CSV document containing all translations for this project.
        response = HttpResponse(content_type='text/csv')
        response[
            'Content-Disposition'] = 'attachment; filename="%s.csv"' % project.name

        return _get_project_strings_csv(project, entities, response)

    if request.method == 'POST':
        if not project_has_strings:
            # We are receiving new strings in a batch.
            new_strings_source = request.POST.get('new_strings', '')
            if _save_new_strings(project, new_strings_source):
                project_has_strings = True  # we have strings now!
        else:
            # Get all strings, find the ones that changed, update them in the database.
            formset = EntityFormSet(request.POST, queryset=entities)
            if formset.is_valid():
                try:
                    formset.save()
                except IntegrityError:
                    # This happens when the user creates a new string. By default,
                    # it has no resource, and that's a violation of the database
                    # constraints. So, we want to make sure all entries have a resource.
                    new_entities = formset.save(commit=False)
                    resource = Resource.objects.filter(project=project).first()
                    for entity in new_entities:
                        if not entity.resource_id:
                            entity.resource = resource

                        # Note that we save all entities one by one. That shouldn't be a problem
                        # because we don't expect users to change thousands of strings at once.
                        # Also, django is smart and ``formset.save()`` only returns Entity
                        # objects that have changed.
                        entity.save()

            # Reinitialize the formset.
            formset = EntityFormSet(queryset=entities)

    data = {
        'project': project,
        'entities': entities,
        'project_has_strings': project_has_strings,
        'entities_form': formset,
    }
    return render(request, 'admin_project_strings.html', data)
Example #2
0
def manage_project_strings(request, slug=None):
    """View to manage the source strings of a project.

    This view is only accessible for projects that do not have a "Source repo". It allows
    admins to add new strings to a project in a batch, and then to edit, remove or comment on
    any strings.

    """
    if not request.user.has_perm('base.can_manage_project'):
        raise PermissionDenied

    try:
        project = Project.objects.get(slug=slug)
    except Project.DoesNotExist:
        raise Http404

    if project.data_source != 'database':
        return HttpResponseForbidden(
            'Project %s\'s strings come from a repository, managing strings is forbidden.'
            % project.name)

    entities = Entity.objects.filter(resource__project=project, obsolete=False)
    project_has_strings = entities.exists()
    formset = EntityFormSet(queryset=entities)

    if request.GET.get('format') == 'csv':
        # Return a CSV document containing all translations for this project.
        response = HttpResponse(content_type='text/csv')
        response[
            'Content-Disposition'] = 'attachment; filename="%s.csv"' % project.name

        return _get_project_strings_csv(project, entities, response)

    if request.method == 'POST':
        if not project_has_strings:
            # We are receiving new strings in a batch.
            new_strings_source = request.POST.get('new_strings', '')
            if _save_new_strings(project, new_strings_source):
                project_has_strings = True  # we have strings now!
                _create_or_update_translated_resources(project)
        else:
            # Get all strings, find the ones that changed, update them in the database.
            formset = EntityFormSet(request.POST, queryset=entities)
            if formset.is_valid():
                resource = Resource.objects.filter(project=project).first()
                entity_max_order = entities.aggregate(
                    Max('order'))['order__max']
                try:
                    # This line can purposefully cause an exception, and that
                    # causes trouble in tests, because all tests are
                    # encapsulated in a single transation. Django thus refuses
                    # to run any other requests after one has failed, until the
                    # end of the transation.
                    # Using transation.atomic here is the way to tell django
                    # that this is fine.
                    # See https://stackoverflow.com/questions/21458387/
                    with transaction.atomic():
                        formset.save()
                except IntegrityError:
                    # This happens when the user creates a new string. By default,
                    # it has no resource, and that's a violation of the database
                    # constraints. So, we want to make sure all entries have a resource.
                    new_entities = formset.save(commit=False)
                    for entity in new_entities:
                        if not entity.resource_id:
                            entity.resource = resource

                        # We also use this opportunity to give the new entity
                        # an order.
                        entity_max_order += 1
                        entity.order = entity_max_order

                        # Note that we save all entities one by one. That shouldn't be a problem
                        # because we don't expect users to change thousands of strings at once.
                        # Also, django is smart and ``formset.save()`` only returns Entity
                        # objects that have changed.
                        entity.save()

                # Update stats with the new number of strings.
                resource.total_strings = (Entity.objects.filter(
                    resource=resource, obsolete=False).count())
                resource.save()
                _create_or_update_translated_resources(project,
                                                       resource=resource)

            # Reinitialize the formset.
            formset = EntityFormSet(queryset=entities)

    data = {
        'project': project,
        'entities': entities,
        'project_has_strings': project_has_strings,
        'entities_form': formset,
    }
    return render(request, 'admin_project_strings.html', data)
Example #3
0
def manage_project_strings(request, slug=None):
    """View to manage the source strings of a project.

    This view is only accessible for projects that do not have a "Source repo". It allows
    admins to add new strings to a project in a batch, and then to edit, remove or comment on
    any strings.

    """
    if not request.user.has_perm('base.can_manage_project'):
        raise PermissionDenied

    try:
        project = Project.objects.get(slug=slug)
    except Project.DoesNotExist:
        raise Http404

    if project.data_source != 'database':
        return HttpResponseForbidden(
            'Project %s\'s strings come from a repository, managing strings is forbidden.'
            % project.name
        )

    entities = Entity.objects.filter(resource__project=project, obsolete=False)
    project_has_strings = entities.exists()
    formset = EntityFormSet(queryset=entities)

    if request.GET.get('format') == 'csv':
        # Return a CSV document containing all translations for this project.
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="%s.csv"' % project.name

        return _get_project_strings_csv(project, entities, response)

    if request.method == 'POST':
        if not project_has_strings:
            # We are receiving new strings in a batch.
            new_strings_source = request.POST.get('new_strings', '')
            if _save_new_strings(project, new_strings_source):
                project_has_strings = True  # we have strings now!
                _create_or_update_translated_resources(project)
        else:
            # Get all strings, find the ones that changed, update them in the database.
            formset = EntityFormSet(request.POST, queryset=entities)
            if formset.is_valid():
                resource = Resource.objects.filter(project=project).first()
                entity_max_order = entities.aggregate(
                    Max('order')
                )['order__max']
                try:
                    # This line can purposefully cause an exception, and that
                    # causes trouble in tests, because all tests are
                    # encapsulated in a single transation. Django thus refuses
                    # to run any other requests after one has failed, until the
                    # end of the transation.
                    # Using transation.atomic here is the way to tell django
                    # that this is fine.
                    # See https://stackoverflow.com/questions/21458387/
                    with transaction.atomic():
                        formset.save()
                except IntegrityError:
                    # This happens when the user creates a new string. By default,
                    # it has no resource, and that's a violation of the database
                    # constraints. So, we want to make sure all entries have a resource.
                    new_entities = formset.save(commit=False)
                    for entity in new_entities:
                        if not entity.resource_id:
                            entity.resource = resource

                        # We also use this opportunity to give the new entity
                        # an order.
                        entity_max_order += 1
                        entity.order = entity_max_order

                        # Note that we save all entities one by one. That shouldn't be a problem
                        # because we don't expect users to change thousands of strings at once.
                        # Also, django is smart and ``formset.save()`` only returns Entity
                        # objects that have changed.
                        entity.save()

                # Update stats with the new number of strings.
                resource.total_strings = (
                    Entity.objects
                    .filter(resource=resource, obsolete=False)
                    .count()
                )
                resource.save()
                _create_or_update_translated_resources(project, resource=resource)

            # Reinitialize the formset.
            formset = EntityFormSet(queryset=entities)

    data = {
        'project': project,
        'entities': entities,
        'project_has_strings': project_has_strings,
        'entities_form': formset,
    }
    return render(request, 'admin_project_strings.html', data)