django GenericForeignkey does not work with object.create() but work fine with save()

633 views Asked by At

I am trying to migrate my db from postgres to mysql. Below is a model Customdata.

user = models.ForeignKey(User, related_name='customdatas')
call_uuid = models.CharField(max_length=50, null=True, blank=True, editable=False)
phone_number = models.CharField(max_length=15)
name = models.CharField(max_length=50, db_index=True)
type = models.CharField(max_length=10, choices=TYPE_CHOICES,
        default='xml')
appcode = models.CharField(max_length=10, choices=APPCODE_CHOICES,
        null=True, blank=True)
value = JSONField(default=[])
remark = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
expiry_time = models.DateTimeField(null=True, blank=True, db_index=True)
reference_type = models.ForeignKey(ContentType, null=True, blank=True)
reference_id = UUIDField('Reference ID', null=True, blank=True)
reference = generic.GenericForeignKey('reference_type', 'reference_id')

When I am creating an entry by using below snippet I face a problem that GenericForeignKey field "reference" does not get updated. Rest every value is perfectly fine.

>> c = Customdata.objects.create(call_uuid=session_uuid + '__'+ str(i),
                    user=order.user, name="voicemail", phone_number=phone_number,
                    type='url', value=data, remark=events['recordingFile'][i],
                    reference=order)
>> c.reference

[Blank value returned]

But after creation if i perform an updation , the value is saved.

>> c.reference = order
>> c.save()
>> c.reference
kdfj-kddl-3933kd-3ed8dl

I have no clue that why "reference" field is not being saved using create but works fine after updating again. This code use to work fine with postgres.

1

There are 1 answers

0
mahajan On

I solved the problem by changing the pre_save function of my custom UUIDField.

>> def pre_save(self, model_instance, add):
>>    old_val = getattr(model_instance, self.attname)
>>    if (self.primary_key and add) and (old_val is None or old_val=="" ):
>>        value = str(uuid.uuid4())
>>        setattr(model_instance, self.attname, value)
>>        return value
>>    else:
>>        return old_val

In case of postgres if old value was not set it was returning as None but in case of mysql it was "". And this was the reason of different behavior in case of create and save.