Why can't save to the database? TypeError: string indices must be integers

Hello all, I’m learning django and testing how it works with API and currently I’m trying to save records from this API to my database and then to display records from the database to the frontend, but it seems like I missed something. I got this error message: TypeError: string indices must be integers

This is my Traceback error:

    response = get_response(request)
  File "/usr/lib/python3/dist-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/lib/python3/dist-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/stela/feedbacksystem/feedback/views.py", line 92, in fetchapi_patients
    Patient.objects.create(first_name=patient['first_name'], last_name=patient['last_name'], email=patient['email'], coreapi_id=patient['ID'])
  File "/usr/lib/python3/dist-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 422, in create
    obj.save(force_insert=True, using=self.db)
  File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 740, in save
    self.save_base(using=using, force_insert=force_insert,
  File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 777, in save_base
    updated = self._save_table(
  File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 870, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 907, in _do_insert
    return manager._insert([self], fields=fields, return_id=update_pk,
  File "/usr/lib/python3/dist-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 1186, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/usr/lib/python3/dist-packages/django/db/models/sql/compiler.py", line 1374, in execute_sql
    for sql, params in self.as_sql():
  File "/usr/lib/python3/dist-packages/django/db/models/sql/compiler.py", line 1316, in as_sql
    value_rows = [
  File "/usr/lib/python3/dist-packages/django/db/models/sql/compiler.py", line 1317, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "/usr/lib/python3/dist-packages/django/db/models/sql/compiler.py", line 1317, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "/usr/lib/python3/dist-packages/django/db/models/sql/compiler.py", line 1258, in prepare_value
    value = field.get_db_prep_save(value, connection=self.connection)
  File "/usr/lib/python3/dist-packages/django/db/models/fields/__init__.py", line 793, in get_db_prep_save
    return self.get_db_prep_value(value, connection=connection, prepared=False)
  File "/usr/lib/python3/dist-packages/django/db/models/fields/__init__.py", line 1435, in get_db_prep_value
    value = self.get_prep_value(value)
  File "/usr/lib/python3/dist-packages/django/db/models/fields/__init__.py", line 1414, in get_prep_value
    value = super().get_prep_value(value)
  File "/usr/lib/python3/dist-packages/django/db/models/fields/__init__.py", line 1274, in get_prep_value
    return self.to_python(value)
  File "/usr/lib/python3/dist-packages/django/db/models/fields/__init__.py", line 1375, in to_python
    parsed = parse_datetime(value)
  File "/usr/lib/python3/dist-packages/django/utils/dateparse.py", line 106, in parse_datetime
    match = datetime_re.match(value)
TypeError: expected string or bytes-like object
 

my function in views.py is:

def fetchapi_patients(request):
    url = 'http://localhost:8000/core/users/roles/superuser'
    headers={"Authorization":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDYzMDg3MzYsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTYwNjMwNTEzNn0.J2wBp8ecA9TebP6L73qZ1OZmo02DwQy9vTySt0fil4c"}
    response = requests.get(url, headers=headers)

    #Read the JSON
    patients = response.json()
    #print(patients)

    #Create a Django model object for each object in the JSON and store the data in django model (in database)
    for patient in patients:
        #print(patient['ID'])
        Patient.objects.create(first_name=patient['first_name'], last_name=patient['last_name'], email=patient['email'], coreapi_id=patient['ID'], created_date=patient['CreatedAt']
    return JsonResponse({'patients': patients})

I tried different thing to make it work and I end up to test if it prints something with:

print(patients)

and that gives me the list of patients in the terminal, that’s how I found that the API works, but can’t find why I get the error when tried to loop the patients so I can save them.

This is my model for Patient:

class Patient(models.Model):
    coreapi_id = models.CharField(max_length=100)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    email = models.EmailField(max_length=100)
    language = models.CharField(max_length=20)
    created_date = models.DateTimeField(default=True)
    lastmodified_date = models.DateTimeField(default=True)

    def str(self):
        return self.email

this is what the json looks like from my API:

[
    {
        "ID": 1,
        "CreatedAt": "2020-12-10T11:10:01.640017+02:00",
        "UpdatedAt": "2020-12-10T11:10:01.643819+02:00",
        "DeletedAt": null,
        "email": "h@go.com",
        "password": "$2a$14$4a8kAnMVrSEhxjmwDMnYQeBklwUcFHmYztIv1wIWlEAEZK0m3NOvi",
        "bearer": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDYzMDg3MzYsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTYwNjMwNTEzNn0.J2wBp8ecA9TebP6L73qZ1OZmo02DwQy9vTySt0fil4c",
        "first_name": "John",
        "last_name": "Pro",
        "phone": "9353456",
        "Roles": [
            {
                "ID": 1,
                "CreatedAt": "2020-12-10T11:10:01.641152+02:00",
                "UpdatedAt": "2020-12-10T11:10:01.641152+02:00",
                "DeletedAt": null,
                "name": "superuser",
                "Users": null
            }
        ]
    }
]

Here is my result in terminal when print(patients) from the API

 [05/Jan/2021 07:46:46] "GET / HTTP/1.1" 200 7427 [{'ID': 1, 'CreatedAt': '2020-12-10T11:10:01.640017+02:00', 'UpdatedAt': '2020-12-10T11:10:01.643819+02:00', 'DeletedAt': None, 'email': 'h@go.com', 'password': '$2a$14$4a8kAnMVrSEhxjmwDMnYQeBklwUcFHmYztIv1wIWlEAEZK0m3NOvi', 'bearer': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDYzMDg3MzYsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTYwNjMwNTEzNn0.J2wBp8ecA9TebP6L73qZ1OZmo02DwQy9vTySt0fil4c', 'first_name': 'John', 'last_name': 'Pro', 'phone': '9353456', 'Roles': [{'ID': 1, 'CreatedAt': '2020-12-10T11:10:01.641152+02:00', 'UpdatedAt': '2020-12-10T11:10:01.641152+02:00', 'DeletedAt': None, 'name': 'superuser', 'Users': None}]}, {'ID': 5, 'CreatedAt': '2021-01-05T09:45:14.862958+02:00', 'UpdatedAt': '2021-01-05T09:45:14.871521+02:00', 'DeletedAt': None, 'email': 'h@go.com', 'password': '$2a$14$uP1ZBDB/A2FZv2V8I.B8zurmt5a.kcirInWftnb7EYmwBk0UsL4Li', 'bearer': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDYzMDg3MzYsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTYwNjMwNTEzNn0.J2wBp8ecA9TebP6L73qZ1OZmo02DwQy9vTySt0fil4c', 'first_name': 'John', 'last_name': 'Pro', 'phone': '9353456', 'Roles': [{'ID': 4, 'CreatedAt': '2021-01-05T09:45:14.866758+02:00', 'UpdatedAt': '2021-01-05T09:45:14.866758+02:00', 'DeletedAt': None, 'name': 'superuser', 'Users': None}]}] [05/Jan/2021 07:46:47] "GET /fetchapipatients/ HTTP/1.1" 200 2```

Any suggestion is most welcome. Thank you in advance.

I updated my question, providing the json and the input from the terminal. In this case this a list withing a list, right? I really appreciate your time and help.

I can’t recreate the problem with the data you’ve posted. This leads me to believe there’s something being lost in how this is being printed. (I’ve got the funny feeling that what you’re actually getting from response.json is a list of strings - just a hunch, no direct evidence of this yet.)
Try adding print(type(patients)) after the print(patients) line and print(type(patient)) as the first statement in the for loop.
It might also be worthwhile to print(response.text) after the request.

Finally, to avoid having the forum software distort what you’re posting as printed output, please enclose your print output between the three backtick characters too. (I see you’re already doing that with the code.) I’m guessing it’s the forum software that converted the single quotes to the fancy quotes.

1 Like

Hi, finally I was able to find solution to my problem. It was really simple, but I get super confused. I will provide a solution for someone who has the same problem as me.

The main problem was that I don’t wanted to drop the database and create it again, but I dropped it, run the migrations from the beginning, also added another class(model) for the Role with ForeignKey and relation many-to-may with Patient class, and then I loop first through Patient and then through Role:

def fetchapi_patients(request):
    url = 'http://localhost:8000/core/users/roles/patient'
    headers={"Authorization":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Imhha2FuQGdvLmNvbSIsImV4cCI6MTYwOTkzNzU0Mywib3JpZ19pYXQiOjE2MDk5MzM5NDN9.gAWcHvetwN43n1gJRU1NXNh-2a4JOtXejckR2BC8_3A"}
    response = requests.get(url, headers=headers)

    #Read the JSON
    patients = response.json()

    #Create a Django model object for each object in the JSON and store the data in django model (in database)
    for patient in patients:
            Patient.objects.create(first_name=patient['first_name'], last_name=patient['last_name'], email=patient['email'], coreapi_id=patient['ID'])
            for role in patient['Roles']:
                Role.objects.create(role_name=role['name'])

    return JsonResponse({'patients': patients})

The editor in the forum don’t give me to convert every code or error message here so this needed to be set manually I had no idea about it, but I did it I hope it looks better now.

Note: This appears to be a different problem than what you described yesterday. (Yesterday we were trying to resolve an issue with the “CreatedAt” key in the JSON response.) I’m guessing you found the solution to that and then encountered this subsequent issue?

Actually yes! You are absolutely right, but I I think found my main problem were the models and migrations and not knowing how to properly handle them

Cool! Glad to see you’ve got things working. However, in the future, when you get past one item and need to address a second issue, go ahead and open up a new topic - or at a minimum, add the new issue as a new reply to the current thread. The problem with editing a current issue is that the replies you receive for the first issue may not apply to the edited version, leading to confusion among those coming along later and searching for answers.