0

I have a list of quizzes by category and class. I would like to use bootstrap description lsit alignment to print like

Class XI    Mathematics     Quiz 1
                            Quiz 2
                            Quiz 3
            Physics         Quiz 3
                            Quiz 4
Class XII   History         Quiz 7
                            Quiz 8

using

<dl class="row">
  <dt class="col-sm-3">Class XI</dt>
  <dd class="col-sm-3">Mathematics</dd>
  <dd class="col-sm-3">Quiz 1</dd>
</dl>

How do I write my django for loop using regroup? Thank you for the help.

class Quiz(models.Model):

    title = models.CharField(
        verbose_name=_("Title"),
        max_length=300, blank=False)
     
    category = models.ForeignKey(
        Category, null=True, blank=True,
        verbose_name=_("Category"), on_delete=models.CASCADE)

class Category(models.Model):

    category = models.CharField(verbose_name=_("Category"),max_length=250, blank=True, null=True)
    
    class_id = models.ForeignKey(studentclass, null=True, blank=True, on_delete=models.CASCADE)  

class studentclass(models.Model):

    class_id= models.CharField(primary_key=True,max_length=5)
    classVal =models.CharField(max_length=255, null=True, blank=True)
1
  • Please show your model for this. Commented Mar 12, 2021 at 11:51

2 Answers 2

1

Firstly we will select all the studentclass and use prefetch_related [Django docs] to prefetch all the related Category and Quiz instances. We can also query for all the Quiz instances and use select_related [Django docs] which will have the benefit of only one query to the database but will have the drawback of more objects created in memory at python side.

object_list = studentclass.objects.all().prefetch_related('category_set__quiz_set')

Note: This will variable should be passed in the context.

Now we need to render the to the template. You want do display some things only if they have changed. You can use the ifchanged template tag for this purpose:

{% for student_class in object_list %}
    {% for category in student_class.category_set.all %}
        {% for quiz in category.quiz_set.all %}
            <dl class="row">
                <dt class="col-sm-3">{% ifchanged student_class.classVal %}{{ student_class.classVal }}{% endifchanged %}</dt>
                <dd class="col-sm-3">{% ifchanged student_class.classVal category.category %}{{ category.category }}{% endifchanged %}</dd>
                <dd class="col-sm-3">{{ quiz.title }}</dd>
            </dl>
        {% endfor %}
    {% endfor %}
{% endfor %}

This will cause {{ student_class.classVal }} to be rendered only if it's value has changed from the previous iteration. Also {{ category.category }} will be rendered only if either it has changed or the class has changed.

Note: You can try with the selecting Quiz instances with order_by on category and the categories class_id and using select_related to get them. It all depends on which query would be more efficient for you.

Sign up to request clarification or add additional context in comments.

2 Comments

what is 'category__quiz' its not recognized, I am getting error. Cannot find 'category' on studentclass object, 'category__quiz' is an invalid parameter to prefetch_related()
@stackoverflowrohit edited try with 'category_set__quiz_set' instead.
0

I assume in your template file you have a list like this:

[
    {"class": "CLASS XI", "category": "Mathematics", "quiz": "Quiz 1"},
    {"class": "CLASS XI", "category": "Mathematics", "quiz": "Quiz 2"},
    {"class": "CLASS XI", "category": "Physics", "quiz": "Quiz 3"},
    {"class": "CLASS XII", "category": "Physics", "quiz": "Quiz 4"},
    {"class": "CLASS XII", "category": "Physics", "quiz": "Quiz 5"},
    {"class": "CLASS XII", "category": "History", "quiz": "Quiz 6"},
    {"class": "CLASS XII", "category": "History", "quiz": "Quiz 7"}
]

I couldn't have chance to test but this should work

{% regroup quizes by class_name as class_list %} 
<ul>
{% for class_name in class_name_list %}
    <li>{{ class_name.grouper }}
    <ul>
        {% for quiz in class_name.list %}
          <li>{{ quiz.title }}</li>
        {% endfor %}
    </ul>
    </li>
{% endfor %}
</ul>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.