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)
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)
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)