Search code examples
pythondjangomodelprimary-key

Django Error: Question matching query does not exist() Updating Questions and Choices to Primary Keys


I am currently attempting the official Django tutorial polls app. It has asked me to create questions for a poll app and than after that create answer choices. I made a mistake creating the questions and somehow made an empty query set which I believe set the primary key to 1 and 2 respectively for the blank questions. I went on to create questions 3, 4, and 5. I realized the blanks were there an I attempted to delete the two questions. After running the delete() command I removed them. I figured that the primary keys would be removed and everything would slide back into place. My question who invented python remained at pk=3.

Now I am wondering what to do. Should I create answer choices off of primary key id 3 and run with it? Or should I find a way to reassign the answer choices.

Well, I have asked the Django forums website and someone recommended to me that I run the command

`[(q.id, q.question_text) for q in Question.objects.all()]'

this command output:

>>> [(q.id, q.question_text) for q in Question.objects.all()]
[(3, 'Who invented python?'), (4, 'This question was changed by dot notation on the object.'), (5, 'Who invented Django?')]
>>> clear

What steps have I taken to solve the problem?

  • I have checked the instructions on the tutorial website for a way to update the empty slot, and I have looked for a way to add a question back in so that it would take the primary key slot one but - I have only found that my way would create another question with a primary key for next in order.
  • I looked at state overflow articles and they are saying do not touch the primary key.
  • I have also asked the Django forum on discord as well.

What am I expecting

I am hoping for a solution where I can have a question and its answer choices take up the pk=1 and 2 slots even though there are questions for pk=3 and 4 and so on.


Solution

  • If you must do this, the following code can achieve your needs, but it will affect performance.

    from django.db import models
    from django.db.models import Min
    
    def get_next_id(Model):
        ids = set(Model.objects.values_list('id', flat=True))
        min_id = Model.objects.all().aggregate(Min('id'))['id__min'] or 1
        while min_id in ids:
            min_id += 1
        return min_id
    
    class Question(models.Model):
        ...
        def save(self, *args, **kwargs):
            if not self.pk and Question.objects.filter(pk=self.pk).exists():
                self.pk = get_next_id(Question)
            super(Question, self).save(*args, **kwargs)