djangodjango-modelsormdjango-orm

get_or_create returning error that multiple value of objects exist when I check same parameters with filter it retuns 0 objects


I am trying to use get_or_create method to see if a record exists. If the record exists do nothing otherwise create it.

This model is basically used on the command that is failing

 class modelStudentExamsPerformed(models.Model):
        patient = models.ForeignKey(modelPatient)
        student = models.ForeignKey(modelStudent,on_delete=models.CASCADE)
        normalBodyPart = models.ForeignKey(modelNormalBodyPartResult,default=None,blank=True,null=True)
        abnormalBodyPart = models.ForeignKey(modelAbnormalBodyPartResult,default=None,blank=True,null=True)
        tool = models.CharField(max_length=128, default="")

Now this is the command that is using the above model and failing

exams.modelStudentExamsPerformed.objects.get_or_create()(patient=patient_qset, student=stud_qset,abnormalBodyPart=qset[0],normalBodyPart=None,date=None)

The above statement gives me the error :

get() returned more than one modelStudentExamsPerformed -- it returned 2!

Now this is where I am having trouble. When I look into the database through my admin I do notice two objects but those objects both have a value associated with normalBodyPart and their abnormalBodyPart is empty.Since I explicitly specified and assigned a value to abnormalBodyPart why does django say that two items already exist ? I hope this makes sense .

Let e explain this another way as well suppose there are two statements 1 and 2. Statement 1 gets or creates a record based on a specified parameter . This get or create fails as django thinks there are already two records. However statement 2 uses the same exact parameters and returns 0 records. Why is that ? What am I missing and not understanding here ?

Statement 1:

exams.modelStudentExamsPerformed.objects.get_or_create()(patient=patient_qset, student=stud_qset,abnormalBodyPart=qset[0],normalBodyPart=None,date=None)

when clearly none of the objects in this table have a value for abnormalBodyPart. I validated this by doing the following

Statement 2:

k = exams.modelStudentExamsPerformed.objects.filter(patient=patient_qset, student=stud_qset,abnormalBodyPart=qset[0], normalBodyPart=None,date=None)

The above statment 2 does not return anything. My question is why does Statement 2 not return anything while statement 1 is complaining that there are 2 items already thus failing the get call.


Solution

  • You're invoking get_or_create() without arguments and then invoke the __call__() method on the resulting instance.

    Put the keywords inside the get_or_create to make it work properly. Also study the method signature again: you're missing a defaults argument. The method works like this:

    Sometimes, it's better to illustrate:

    instance, created = Players.objects.get_or_create(
        username='Lagolas',
        defaults={'class': 'ranger', 'gender': 'male'}
    )
    

    Is equivalent to:

    try:
        instance = Players.objects.get(username='Lagolas')
        return instance, False
    except Players.DoesNotExist:
        instance = Players.objects.create(
            username='Lagolas', class='ranger', gender='male'
        )
        return instance, True