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"], ), )