1

I have a model named Run with a manager named RunManager and with a custom save() method as follows.

class RunManager(models.Manager):
    use_for_related_fields = True
    def get_queryset(self):
        queryset = super(RunManager, self).get_queryset()
        queryset = queryset.filter(archived=False)
        return queryset

    def unfiltered_runs(self):
        queryset = super(RunManager, self).get_queryset()
        return queryset

class Run(models.Model):
    name = models.CharField(max_length=256)
    archived = models.BooleanField(default=False)
    objects = RunManager()

    def save(self, *args, **kwargs):
        # some business logic
        super(Run, self).save(*args, **kwargs)

    def archive(self):
        # Some business logic
        self.archived = True
        self.save()

    def recover_archived(self):
        # Some business logic
        self.archived = False
        self.save()

This was an old code where the run.objects were used at several location, so to hide the archived runs I am using the RunManager. Everything was working fine, but now we want to unarchive the runs. So I added the unfiltred_runs() method which shows the list of all the runs along with the archived runs. But when I run recove_archived() method i get following error

IntegrityError: UNIQUE constraint failed: run.id

I know the error is because the db is treating it as a new entry with same id. I know I can completely override the save method but I want to avoid that.

So is there any way to make save method lookup in the unfiltered_runs() queryset instead of regular one.

  • 1
    instead of doing that you could issue an `update()` straight to the database. Start by adding another manager that returns every object and then just do `Run.all_objects.filter(id=self.id).update(archived=False)` after that just reload the run instance from db – ivissani Dec 20 '19 at 22:03
  • Wow, that was simple. But instead of adding another manager, I used the unfiltered_runs() like this, ```Run.objects.unfiltered_runs().filter(pk=self.id).update(archived=False)``` And it worked. Thank you. – Ajit Wadalkar Dec 20 '19 at 22:21

1 Answers1

0

By following @ivissani's suggestion I modified my recover_archived method as follows. And it is working flawlessly.

def recover_archived(self):
    # Some business logic
    Run.objects.unfiltered_runs().filter(pk=self.id).update(archived=False)