Skip to content
Advertisement

How to use get_or_create? Error: get() returned more than one Patient — it returned 7

I have a function for fetch API where I create a Django model object for each object in the JSON and store the data in django model. The problem here is everytime I call the route it creates the records again and again, because I use create method, but I made an research that the best way to stop that is to use get_or_create. So, I tried this method but it looks like I missed something, because I got an error: feedback.models.Patient.MultipleObjectsReturned: get() returned more than one Patient — it returned 7!

this is my code before I have 2 for loops so I can loop through every patient and then through every role and save patient with a role:

# FetchApi for Patients def fetchapi_patients(request):
    url = 'http://localhost:8000/core/users/roles/patient'
    headers={"Authorization":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Imhha2FuQGdvLmNvbSIsImV4cCI6MTYxMDAxMTM0MSwib3JpZ19pYXQiOjE2MTAwMDc3NDF9.k2204d094DNUbEfFt8M_7chukOSjWWwfesPOH5jIiP8"}
    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})

this is when I tried to use get_or_create method:

for patient in patients:
            patientDatabase, created = Patient.objects.get_or_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.get_or_create(role_name=role['name'])
                

    return JsonResponse({'patients': patients})

this is my models.py:

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(auto_now_add=True)

    def str(self):
        return self.email

class Role(models.Model):
    role_id = models.ManyToManyField(Patient)
    role_name = models.CharField(max_length=100)

    def __str__(self):
        return self.role_name

The Traceback error:

Traceback (most recent call last):   File "/usr/lib/python3/dist-packages/django/core/handlers/exception.py", line 34, in inner
    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 88, in fetchapi_patients
    patientDatabase, created = Patient.objects.get_or_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 538, in get_or_create
    return self.get(**kwargs), False   File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 410, in get
    raise self.model.MultipleObjectsReturned( feedback.models.Patient.MultipleObjectsReturned: get() returned more than one Patient -- it returned 7!

I read the official documentation but there are a some misunderstanding that are not very clear to me about get_or_create method for example I want to check the users only by their email, because I read that it should be something “unique”, so get_or_create checks every field in my model or..? I hope my question is clear if it’s not please let me know

Advertisement

Answer

There simply are multiple objects with the same (first_name, last_name, email, coreapi_id), and get_or_create refuses to do anything since it’s likely a logic problem.

The same would happen with just .get() (which is indeed what .get_or_create() does).

If you mean to e.g. only get the Patient using the coreapi_id field, but if no Patient with that data exists, create them using the other fields, you’ll want to use the defaults argument:

patientDatabase, created = Patient.objects.get_or_create(
    coreapi_id=patient["ID"],
    defaults=dict(
        first_name=patient["first_name"],
        last_name=patient["last_name"],
        email=patient["email"],
    ),
)

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement