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