TypeError: string indices must be integers - Saving data from a JSON to the database

0

I have the following situation:

The model RehabilitationSession in addition to other data these fields of interest:

class RehabilitationSession(models.Model):
             ...
    minimum = models.DecimalField(
        max_digits=5,decimal_places=2,verbose_name='Valor mínimo'
    )

    maximum = models.DecimalField(
        max_digits=5, decimal_places=2,verbose_name='Valor máximo'
    )

    median = models.DecimalField(
        max_digits=5,decimal_places=2,verbose_name='Valor medio'
    )

    mode = models.DecimalField(
        max_digits=5, decimal_places=2,verbose_name='Valor moda'
    )
                  ...

In this model, your information is completed with a JSON file that provides information from an external application and precisely that JSON gives me the values for these fields of minimum , median , mode and maximum

Then it is in the behavior of the Detail view of an object RehabilitationSession where I want to take that information from the JSON document and save it to the database.

The JSON document is this. I give it to know in the totality of its structure with the aim of being able to size up the error that I have in case such:

{
  "paciente": {
    "id": 1234,
    "nombre": "Pablo Andrés Agudelo Marenco",
    "sesion": {
      "id": 3,
      "juego": [
        {
          "nombre": "bonzo",
          "nivel": [
            {
              "id": 1234,
              "nombre": "caida libre",
              "segmento": [
                {
                  "id": 12345,
                  "nombre": "Hombro",
                  "movimiento": [
                    {
                      "id": 1234,
                      "nombre": "Flexion",
                      "metricas": [
                        {
                          "min": 12,
                          "max": 34,
                          "media": 23,
                          "moda": 20
                        }
                      ]
                    }
                  ]
                }
              ],
              "___léeme___": "El array 'iteraciones' contiene las vitorias o derrotas con el tiempo en segundos de cada iteración",
              "iteraciones": [
                {
                  "victoria": true,
                  "tiempo": 120
                },
                {
                  "victoria": false,
                  "tiempo": 232
                }
              ]
            }
          ]
        }
      ]
    }
  }
}

In my class-based view of the detail of a RehabilitationSession object is where I read the JSON document and compare the identifiers of both the object in the database and the JSON ( ["paciente"]["sesion"]["id"] ) and if they match I proceed with the data storage.

I have the following:

class RehabilitationSessionDetail(LoginRequiredMixin,DetailView):
    model = RehabilitationSession
    template_name = 'rehabilitationsession_detail.html'
    context_object_name = 'sessiondetail'

    def get_context_data(self, **kwargs):
        context=super(RehabilitationSessionDetail, self).get_context_data(**kwargs)
        user = self.request.user

        with open('ProcessedMetricsFinal.json') as data_file:
            session_data=json.loads(data_file.read())
            context['session_data'] = session_data

            #Capturar el ID de la sesión del JSON
            session_id_json = session_data["paciente"]["sesion"]["id"]

            #Capturar el ID de la sesión de la base de datos
            session_id_db=int(self.kwargs.get('pk'))

            #Comparar esos dos ID, si son iguales:
            if session_id_db==session_id_json:
                # Guardando datos a la base de datos
                for record in session_data:
                    RehabilitationSession.objects.filter(id=session_id_db).update(
                        minimum=record['min'],
                        maximum=record['max'],
                        median=record['media'],
                        mode=record['moda'])
            else:
                context=super(RehabilitationSessionDetail, self).get_context_data(**kwargs)
            return context

Then when I go to my detail url, which is the one that calls this view, when the condition of comparing the ids of both the JSON document and the object in the database is met, I get the following error:

File "/home/bgarcial/workspace/neurorehabilitation_project/medical_encounter_information/views.py", line 187, in get_context_data
    minimum=record['min'],
TypeError: string indices must be integers
[17/Nov/2016 02:07:17] "GET /sesiones-de-rehabilitacion/3 HTTP/1.1" 500 122694

I do not know if maybe as I am investigating in my view by the keys min , max , media , moda which are in a higher indentation level ... should go through it with several indexes in my cycle for ?

Any orientation is highly appreciated.

    
asked by bgarcial 17.11.2016 в 03:13
source

1 answer

2

Your error is that you are iterating over a string, the error says that the indexes can not be 'strings' if not 'integers' ... Remember that when iterating over a dictionary you can not do it like a normal list (knowing that the JSON are dictionaries for python), so if you go through them as you are doing in this line:

...
for record in session_data: # estas accediendo a cada llave de el JSON principal
...

The correct thing would be to iterate over the dictionary like this: for key, value in session_data.items(): but not to damage your code a lot, if you know that what you have in your variable record are strings, you should iterate like this:

...
for key in session_data:
    record = session_data[key]['sesion']['juego'][0]['nivel'][0]['segmento'][0]['movimiento'][0]['metricas'][0]
    RehabilitationSession.objects.filter(id=session_id_db).update(
        minimum=record['min'],
        maximum=record['max'],
        median=record['media'],
        mode=record['moda']
    )
...

The reason I use the indexes 0 is because your JSON contains arrays and within the arrays are the dictionaries ...

I hope with this answer I have oriented you and you can improve the code in many ways, it does not have to be this way, I do it just for demonstration purposes ... any questions, comments

    
answered by 17.11.2016 / 16:15
source