I have a query where I should avoid double entry of the same question. In fact, I would like to get only unique values but, I am using the distinct()
django function which isn’t working.
I have these models:
class QuestionTopic(models.Model): name = models.CharField(max_length=255) question_subject = models.ForeignKey( QuestionSubject, on_delete=models.CASCADE) exam_questions_num = models.IntegerField(null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.name class Meta: ordering = ('created_at',) class Question(models.Model): id = models.CharField(max_length=7, unique=True, primary_key=True, editable=False) question_subject = models.ForeignKey( QuestionSubject, on_delete=models.CASCADE) text = tinymce_models.HTMLField() mark = models.IntegerField(default=1) is_published = models.BooleanField(default=True) question_bank_id = models.CharField(max_length=255, blank=True, null=True) question_topic = models.ForeignKey( QuestionTopic, on_delete=models.CASCADE, null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)
and the query is:
subject = QuestionSubject.objects.get(id=request.POST.get('subject')) question_topics = QuestionTopic.objects.filter( question_subject=subject) questions_list = [] for topic in question_topics: for q in range(topic.exam_questions_num): question = Question.objects.filter( question_subject=subject, question_topic=topic).values_list( 'id', flat=True).order_by('?').distinct().first() questions_list.append(question)
What I would like to achieve is to have all different questions for each different topic inside questions_list
. Which I am not achieving at the moment being the distinct
used inside a loop.
Advertisement
Answer
You can work with a single query with:
subject = QuestionSubject.objects.get(id=request.POST.get('subject')) question_topics = QuestionTopic.objects.filter(question_subject=subject) questions_list = [ question for topic in question_topics for question in Question.objects.filter( question_subject=subject, question_topic=topic ).order_by('?')[: topic.exam_questions_num] ]
This will make O(n) queries with n the number of topics.
If the number of questions is not that large, you can do this with two queries with:
from random import sample subject = QuestionSubject.objects.get(id=request.POST.get('subject')) question_topics = QuestionTopic.objects.filter( question_subject=subject ).prefetch_related('question_set') questions_list = [ question for topic in question_topics for question in sample(topic.question_set.all(), topic.exam_question_num) ]