Lavin_38
Lavin_38

Reputation: 11

Django models design

I am working on a quiz app on Django and have the following models - User, Test, Question and Answer. The Test model acts as a wrapper for the Questions model. This is what my models looks like at present -

models.py

class Test(models.Model):
    def id_count():
        current_count = Test.objects.count()
        current_count += 1
        return current_count
    test_id = models.PositiveIntegerField(default=id_count,primary_key=True)
    test_description = models.CharField(max_length=255)


class Question(models.Model):
    def id_count():
        current_count = Question.objects.count()
        current_count += 1
        return current_count
    test = models.ForeignKey(Test,on_delete=models.CASCADE)
    question_id = 
    models.PositiveIntegerField(default=id_count,primary_key=True) 
    question_text = models.CharField(max_length=255)
    option_one = models.CharField(max_length=12,default="Always")
    option_two = models.CharField(max_length=12,default="Never")

class Answer(models.Model):
    question = models.ForeignKey(Question,on_delete=models.CASCADE)
    customuser = 
           models.ForeignKey(CustomUser,on_delete=models.CASCADE,blank=True, 
           null=True)
    original_answer_score = 
            models.IntegerField(default=-1)

The current models basically allow every user to answer the same question multiple times. How can I design my models to allow every user to answer one question only once? Thanks.


Editing to add the respective view:

class AnswerFormView(SingleObjectMixin, generic.FormView):
template_name = 'tests/question_detail.html'
form_class = forms.AnswerForm
model = models.Answer

def get_success_url(self,*args,**kwargs):
    return reverse('tests:question_detail', args=(self.kwargs['pk'],))

def form_valid(self, form):
    answer = models.Answer.objects.create(
            question=models.Question.objects.get(question_id=self.kwargs['pk']),
            customuser=self.request.user,
            original_answer_score=form.cleaned_data['original_answer_score']
    )       
    return super(AnswerFormView, self).form_valid(form)

Upvotes: 0

Views: 217

Answers (2)

Umesh
Umesh

Reputation: 971

Try following code for you Answer model.

class Answer(models.Model):
    question = models.ForeignKey(Question,on_delete=models.CASCADE)
    customuser = models.ForeignKey(CustomUser,on_delete=models.CASCADE,blank=True, null=True)
    original_answer_score = models.IntegerField(default=-1, editable=False)


    class Meta:
        unique_together = **('question', 'customuser')**
        ordering = ('question')

To answer one question only once you will need to add editable=False in your field so that it cannot be edited once entered.

To make the combination of quetion and customuser you will need to add unique_together in you Meta class of Model.

Upvotes: 1

olivecoder
olivecoder

Reputation: 2914

Make customer and question a compound index in the Answer table.

Something like:

class Answer(...
    class Meta:
        unique_together = ( 'customuser', 'question' )
    ...

Just put the right field names in that tuple and the uniqueness will be enforced by the database.

More info: https://docs.djangoproject.com/en/2.0/ref/models/options/#unique-together

Upvotes: 1

Related Questions