'Why I am getting a single array object instead of all array values in Django rest framework?

I am using Django rest framework for API and pandas to parse excel file. But my Django model takes only the last row of excel file and returns it. I want all rows to be posted and returned. Here is my code.

models.py

class BusinessImpact(models.Model, ModelWithCreateFromDict):
    client = models.ForeignKey(
        accounts_models.Client, on_delete=models.CASCADE)
    business_process = models.ForeignKey(
        BusinessProcess, on_delete=models.CASCADE)
    hierarchy = models.CharField(max_length=255)
    business_assets = models.CharField(max_length=255)
    asset_name = models.CharField(max_length=255)
    vendors = models.CharField(max_length=255)
    product = models.CharField(max_length=255)
    version = models.CharField(max_length=10)
    cpe = models.CharField(max_length=255)
    asset_type = models.CharField(max_length=10)
    asset_categorization = models.CharField(max_length=255)
    asset_risk = models.CharField(max_length=50)
    _regulations = models.TextField(blank=True)
    _geolocation = models.TextField(blank=True)

    def __str__(self) -> str:
        return self.hierarchy + " - " + self.business_assets

    @property
    def regulations(self) -> List[str]:
        return self._regulations.split(",")

    @property
    def geolocation(self) -> List[str]:
        return self._geolocation.split(",")

    excel_titles = {
        "hierarchy": "Hierarchy",
        "business_assets": "Business Assets",
        "asset_name": "Asset Name",
        "vendors": "Vendors",
        "product": "Product",
        "version": "Version",
        "cpe": "CPE",
        "asset_type": "Asset Type",
        "asset_categorization": "Asset Categorization",
        "asset_risk": "Asset Risk",
        "_regulations": "Regulations",
        "_geolocation": "GeoLocation",
    }

    important_fields = ["hierarchy", "business_assets", "asset_name"]

ModelWithCreateFromDict.py

from utils.extended_models import helpers
class ModelWithCreateFromDict:


    @classmethod
    def all_important_fields_are_provided(cls, dict):
        if not hasattr(cls, 'important_fields'): return
        res = True
        for field in getattr(cls, 'important_fields'):
            if dict.get(field) == None or dict.get(field) == "": 
                # raise Exception("BY MIKE := {} is important field and not been provided".format(field))
                print("BY MIKE := {} is important field and not been provided".format(field))
                res = False
        return res
        
    @classmethod
    def create_obj_form_dict(cls, dict):

        data = {}
        arr_data = {}

        # This has side effect it might create objects on db if 
        # it can't get them create_object_with_name method
        for val in dict:
            try:
                field = cls._meta.get_field(val)
                field_type = field.get_internal_type()

                if field_type != "ArrayReferenceField" and field_type != "ForeignKey":
                    data[val] = dict[val]
                elif field_type == "ForeignKey":
                    data[val] = helpers.get_or_create_foreignkey_object_by_name_or_id(
                        field.related_model, dict[val]
                    )
                elif field_type == "ArrayReferenceField":
                    arr_data[val] = helpers.get_array_objects_by_name(
                        field.related_model, dict[val]
                    )
                    # ADD CASE FOR ArrayField
            except Exception as e:
                print(e)
        
        if not cls.all_important_fields_are_provided(data):
            # NOTE if all important fields are not on dict ignore that row
            return

        try:
            obj = cls.objects.create(**data)
            for ad in arr_data:
                many_to_many_field = getattr(obj, ad)
                for arr_val in arr_data[ad]:
                    many_to_many_field.add(arr_val)

            return obj
        except Exception as e:
            # NOTE if DB object is not able to be created from dict for some reason ignore that dict
            print(e)
            return None

ExcelHandlingView

 import time
  from accounts import models
  from utils.extended_models.ExtendedModel 
  import ModelWithCreateFromDict  

class ExcelHandlingView:

    @classmethod
    def isNaN(cls, num):
        return num != num

    @classmethod
    def get_value_or_none(cls, val):
        if cls.isNaN(val):
            return None
        return str(val).strip()

    @classmethod
    def get_excel_fields(cls, dict):
        res = []
        for v in dict.values():
            res.append(v)
        return res

    @classmethod
    def can_model_handle_ExcelHandlingView(cls, model):
        if not hasattr(model, 'excel_titles'):
            raise Exception(
                "`BY MIKE` := {} has got no excel_titles defined".format(model))
        if not hasattr(model, 'create_obj_form_dict'):
            raise Exception("`BY MIKE` := {} is not a child of {}".format(
                model, ModelWithCreateFromDict))


@classmethod
def create_model_object(cls, model, row, other_dict_data={}):
    # cls.delete_every_recore_on_that_model(model)
    data = other_dict_data
    for d in model.excel_titles:
        data[d] = cls.get_value_or_none(row.get(model.excel_titles[d]))
    return model.create_obj_form_dict(data)

views.py

class UploadBusinessImpactExcelByClientAdmin(APIView, ExcelHandlingView):

    def post(self, request):
        self.can_model_handle_ExcelHandlingView(models.BusinessImpact)

        serializer = serializers.ExcelFileAndBusinessProcessUploader(
            data=request.data)
        if serializer.is_valid():
            data = serializer.validated_data
            file = data.get("file")
            client = request.user.client
            business_process_id = data.get("business_process")

            try:
                business_process = get_business_process_by_client(
                    client, business_process_id
                )
            except (
                models.BusinessProcess.DoesNotExist,
                accountModels.Client.DoesNotExist,
            ) as e:
                return Response(
                    "business process or client does not exist",
                    status=status.HTTP_404_NOT_FOUND,
                )

            if (
                file.content_type
                == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            ):
                # self.delete_every_recore_on_that_model(models.BusinessImpact)
                self.delete_every_record_that_match_criteria(
                    models.BusinessImpact,
                    {"client": client, "business_process": business_process},
                )
                excel_file = pd.read_excel(file))
                data = pd.DataFrame(
                    excel_file,
                    columns=self.get_excel_fields(
                        models.BusinessImpact.excel_titles),
                )

                for _, row in data.iterrows():
                    self.create_model_object(
                        models.BusinessImpact,
                        row,
                        {"client": client.id, "business_process": business_process.id},
                    )

                return Response("Successfully Loaded data from excel.")

            else:
                return Response(
                    {"file": ["File type must be excel with .xlxs extension."]},
                    status=status.HTTP_400_BAD_REQUEST,
                )

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

My API is working well but It's not reading all rows instead it reads the last row and returns it. Here is console log of what I get from the API.

0:
asset_categorization: "Sensitive"
asset_name: "Primary Data Center"
asset_risk: "High"
asset_type: "I"
business_assets: "Infrastructure"
business_process: {id: 1, name: 'Credit Management'}
client: 1
cpe: "cpe:2.3:a:oracle:peoplesoft_enterprise:8.22.14"
hierarchy: "L7 / DATA CENTER"
id: 1170
product: "gbfg"
vendors: "ghg"
version: "fgf"
_geolocation: "cvb v"
_regulations: "gvbv"
[[Prototype]]: Object

What can I do to read all rows?

Thanks



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source