Reputation: 11
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
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
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