Reputation: 9583
I have a problem with Django Rest Framework. This app I'm building is Avatar. User can update his/her own avatar, then avatar auto save with my path I defined (/users_id/photoset_id/filename.png). So I make function to save like this code:
def avatar_file_path(instance, filename):
ext = filename.split('.')[-1]
filename = '%s.%s' % (instance.id, ext)
return "users/%s/avatar/%s_%s" %(instance.user.id, instance.photoset.id, filename)
class Avatar(models.Model):
user = models.ForeignKey(User, related_name='avatar_set', null=True)
photoset = models.ForeignKey(PhotoSet, null=True, blank=True)
primary = models.BooleanField(default=True)
caption = models.TextField(blank=True, null=True)
image = models.ImageField(max_length=1024, upload_to=avatar_file_path)
is_public = models.BooleanField(_('is public'), default=True, help_text=_('Public photographs will be displayed in the default views.'))
date_uploaded = models.DateTimeField(default=datetime.datetime.now)
def save(self, force_insert=False, force_update=False, *args, **kwargs):
# Make one primary Avatar
if self.primary:
avatars = Avatar.objects.filter(user=self.user, primary=True).exclude(id=self.id)
avatars.update(primary=False)
# Set default photoset
if self.photoset is None:
if not PhotoSet.objects.filter(user=self.user, photoset_type=3).exists():
PhotoSet.objects.create(user=self.user, photoset_type=3, title='Profile Pictures')
self.photoset = PhotoSet.objects.get(user=self.user, photoset_type=3)
if PhotoSet.objects.filter(user=self.user, photoset_type=3).exists():
self.photoset = PhotoSet.objects.get(user=self.user, photoset_type=3)
# Model Save override
if self.id is None:
saved_image = self.image
self.image = None
super(Avatar, self).save(*args, **kwargs)
self.image = saved_image
super(Avatar, self).save(force_insert, force_update, *args, **kwargs)
When I create serializers POST with Django Rest Framework:
class AvatarCreateUpdateSerializer(ModelSerializer):
class Meta:
model = Avatar
fields = [
'user',
'image',
'caption',
'is_public',
]
Error Log Tracking in line: super(Avatar, self).save(force_insert, force_update, *args, **kwargs)
Why I face with this problem and how can I fix this? Thank you in advance!
Upvotes: 1
Views: 3217
Reputation: 511
The problem is that the save function gets passed "forced_insert=True" by the rest framework. As you are saving twice with the same data, it is trying to force an insert of the same primary key twice.
A solution is that after the first save is to reset that forced_insert by adding
kwargs['force_insert'] = False
before the second save. That will allow Django to use the update method, hence not try and create the same primary key twice.
Upvotes: 0
Reputation: 9583
Issue Fixed: Change super(Avatar, self).save(force_insert, force_update, *args, **kwargs)
into super(Avatar, self).save(*args, **kwargs)
Upvotes: 0
Reputation: 1514
You are calling two times the save()
method on the base class on your Model:
Here:
super(Avatar, self).save(*args, **kwargs)
And here:
super(Avatar, self).save(force_insert, force_update, *args, **kwargs)
As the comment below says, you should be using update_or_create
or get_or_create
to handle case like this.
Upvotes: 3