<commit_before>from rest_framework.decorators import detail_route
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from rest_framework import status
from django.db import transaction

from . import models, serializers
from . import filters as works_filters
from balarco import utils


class WorkTypeViewSet(utils.GenericViewSet):
    """ViewSet for WorkType CRUD REST Service that inherits from utils.GenericViewSet
    """
    obj_class = models.WorkType
    queryset = models.WorkType.objects.filter(is_active=True)
    serializer_class = serializers.WorkTypeSerializer
    filter_class = works_filters.WorkTypeFilter


class ArtTypeViewSet(utils.GenericViewSet):
    """ViewSet for ArtType CRUD REST Service that inherits from utils.GenericViewSet
    """
    obj_class = models.ArtType
    queryset = models.ArtType.objects.filter(is_active=True)
    serializer_class = serializers.ArtTypeSerializer
    filter_class = works_filters.ArtTypeFilter


class IgualaViewSet(utils.GenericViewSet):
    """ViewSet for Iguala CRUD REST Service that inherits from utils.GenericViewSet
    """
    obj_class = models.Iguala
    queryset = models.Iguala.objects.filter(is_active=True)
    serializer_class = serializers.IgualaSerializer
    filter_class = works_filters.IgualaFilter

    @transaction.atomic
    def create(self, request):
        """Overrided method because an Iguala has a list of Art types associated.
        All objects are sended directly in the same WS and here are processed.
        A roll back is done in case of failure so it's an atomic function
        """
        sid = transaction.savepoint()
        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            new_obj = self.obj_class.objects.create(**serializer.validated_data)
            if 'art_iguala' in request.data:
                art_igualas = request.data['art_iguala']
                for art_iguala in art_igualas:
                    art_iguala['iguala'] = new_obj.id
                    if not utils.save_object_from_data(models.ArtIguala,
                                                       serializers.ArtIgualaSerializer,
                                                       art_iguala):
                        transaction.savepoint_rollback(sid)
                        return utils.response_object_could_not_be_created(self.obj_class)

            return Response(self.serializer_class(new_obj).data, status=status.HTTP_201_CREATED)

        transaction.savepoint_rollback(sid)
        return utils.response_object_could_not_be_created(self.obj_class)

    @transaction.atomic
    def update(self, request, pk=None):
        sid = transaction.savepoint()
        queryset = self.obj_class.objects.filter(is_active=True)
        obj = get_object_or_404(queryset, pk=pk)
        serializer = self.serializer_class(obj, data=request.data, partial=True)
        if serializer.is_valid():
            updated_obj = serializer.save()
            if 'art_iguala' in request.data:
                art_igualas = request.data['art_iguala']
                for art_iguala in art_igualas:
                    art_iguala['iguala'] = updated_obj.id
                    art_type_id = art_iguala['art_type']
                    try:
                        update_art_iguala_obj = models.ArtIguala.objects.get(iguala=updated_obj.id,
                                                                             art_type=art_type_id)
                    except models.ArtIguala.DoesNotExist:
                        update_art_iguala_obj = None
                    if update_art_iguala_obj is not None:
                        if not utils.update_object_from_data(serializers.ArtIgualaSerializer,
                                                             update_art_iguala_obj,
                                                             art_iguala):
                            transaction.savepoint_rollback(sid)
                            return utils.response_object_could_not_be_created(self.obj_class)
                    else:
                        if not utils.save_object_from_data(models.ArtIguala,
                                                           serializers.ArtIgualaSerializer,
                                                           art_iguala):
                            transaction.savepoint_rollback(sid)
                            return utils.response_object_could_not_be_created(self.obj_class)

            return Response(self.serializer_class(updated_obj).data, status.HTTP_200_OK)

        transaction.savepoint_rollback(sid)
        return utils.response_object_could_not_be_created(self.obj_class)

    def partial_update(self, request, pk=None):
        return self.update(request, pk)
<commit_msg>First version of the creation of a csv to download<commit_after>import csv

from rest_framework.decorators import detail_route
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from rest_framework import status
from django.db import transaction
from django.http import HttpResponse

from . import models, serializers
from . import filters as works_filters
from balarco import utils


class WorkTypeViewSet(utils.GenericViewSet):
    """ViewSet for WorkType CRUD REST Service that inherits from utils.GenericViewSet
    """
    obj_class = models.WorkType
    queryset = models.WorkType.objects.filter(is_active=True)
    serializer_class = serializers.WorkTypeSerializer
    filter_class = works_filters.WorkTypeFilter


class ArtTypeViewSet(utils.GenericViewSet):
    """ViewSet for ArtType CRUD REST Service that inherits from utils.GenericViewSet
    """
    obj_class = models.ArtType
    queryset = models.ArtType.objects.filter(is_active=True)
    serializer_class = serializers.ArtTypeSerializer
    filter_class = works_filters.ArtTypeFilter


class IgualaViewSet(utils.GenericViewSet):
    """ViewSet for Iguala CRUD REST Service that inherits from utils.GenericViewSet
    """
    obj_class = models.Iguala
    queryset = models.Iguala.objects.filter(is_active=True)
    serializer_class = serializers.IgualaSerializer
    filter_class = works_filters.IgualaFilter

    @transaction.atomic
    def create(self, request):
        """Overrided method because an Iguala has a list of Art types associated.
        All objects are sended directly in the same WS and here are processed.
        A roll back is done in case of failure so it's an atomic function
        """
        sid = transaction.savepoint()
        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            new_obj = self.obj_class.objects.create(**serializer.validated_data)
            if 'art_iguala' in request.data:
                art_igualas = request.data['art_iguala']
                for art_iguala in art_igualas:
                    art_iguala['iguala'] = new_obj.id
                    if not utils.save_object_from_data(models.ArtIguala,
                                                       serializers.ArtIgualaSerializer,
                                                       art_iguala):
                        transaction.savepoint_rollback(sid)
                        return utils.response_object_could_not_be_created(self.obj_class)

            return Response(self.serializer_class(new_obj).data, status=status.HTTP_201_CREATED)

        transaction.savepoint_rollback(sid)
        return utils.response_object_could_not_be_created(self.obj_class)

    @transaction.atomic
    def update(self, request, pk=None):
        sid = transaction.savepoint()
        queryset = self.obj_class.objects.filter(is_active=True)
        obj = get_object_or_404(queryset, pk=pk)
        serializer = self.serializer_class(obj, data=request.data, partial=True)
        if serializer.is_valid():
            updated_obj = serializer.save()
            if 'art_iguala' in request.data:
                art_igualas = request.data['art_iguala']
                for art_iguala in art_igualas:
                    art_iguala['iguala'] = updated_obj.id
                    art_type_id = art_iguala['art_type']
                    try:
                        update_art_iguala_obj = models.ArtIguala.objects.get(iguala=updated_obj.id,
                                                                             art_type=art_type_id)
                    except models.ArtIguala.DoesNotExist:
                        update_art_iguala_obj = None
                    if update_art_iguala_obj is not None:
                        if not utils.update_object_from_data(serializers.ArtIgualaSerializer,
                                                             update_art_iguala_obj,
                                                             art_iguala):
                            transaction.savepoint_rollback(sid)
                            return utils.response_object_could_not_be_created(self.obj_class)
                    else:
                        if not utils.save_object_from_data(models.ArtIguala,
                                                           serializers.ArtIgualaSerializer,
                                                           art_iguala):
                            transaction.savepoint_rollback(sid)
                            return utils.response_object_could_not_be_created(self.obj_class)

            return Response(self.serializer_class(updated_obj).data, status.HTTP_200_OK)

        transaction.savepoint_rollback(sid)
        return utils.response_object_could_not_be_created(self.obj_class)

    def partial_update(self, request, pk=None):
        return self.update(request, pk)

    @detail_route(methods=['get'], url_path='report')
    def report(self, request, pk=None):
        queryset = models.Iguala.objects.filter(is_active=True)
        iguala = get_object_or_404(queryset, pk=pk)
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="{}.csv"'.format(iguala.name)

        writer = csv.writer(response)
        writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
        writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])

        return response

{'fraction_non_alphanumeric': 0.06863698230604705, 'fraction_numerical': 0.00262492708535874, 'mean_word_length': 2.0901171522979873, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 31, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '295923', 'n_tokens_mistral': 2814, 'n_tokens_neox': 2711, 'n_words': 543}