KitKit
KitKit

Reputation: 9583

Django Rest Framework: Duplicate key value violates unique constraint

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',
        ]

It goes problem: enter image description here

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

Answers (3)

dwagon
dwagon

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

KitKit
KitKit

Reputation: 9583

Issue Fixed: Change super(Avatar, self).save(force_insert, force_update, *args, **kwargs) into super(Avatar, self).save(*args, **kwargs)

Upvotes: 0

Clément Denoix
Clément Denoix

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

Related Questions