regroup problem

I have this model with def values “Weeknr” and “Daynr”

class Shift(models.Model):
    status = models.ForeignKey('Status', default=1, on_delete=models.CASCADE)
    shift_title = models.CharField('Shift title', max_length=255)
    function = models.ForeignKey('Function', on_delete=models.CASCADE)
    start_date = models.DateField('Start date')
    start_time = models.TimeField('Start time')
    end_date = models.DateField('End date')
    end_time = models.TimeField('End time')
    site = models.ForeignKey('Site', blank=True, null=True, on_delete=models.CASCADE)
    user = models.ForeignKey('Shiftuser', blank=True, null=True, on_delete=models.CASCADE)

    class Meta:
        ordering = ('start_date', 'start_time')

    def __str__(self):
        return self.shift_title

    def Daynr(self):
        daynr = self.start_date.isoweekday()
        return daynr

    def Weeknr(self):
        weeknr = self.start_date.isocalendar()[1]
        return weeknr

I want to use “” Weeknr" in a regroup but I can’t get it working. Is it possible to use this def value?

Here my regroup code:

 {% regroup shifts|dictsort:"Weeknr" by Weeknr as newlist %}

        {% for Weeknr in newlist %}
            <div class="grid-container"><h1>{{ Weeknr.grouper }}</h1></div>
                {% for item in Weeknr.list %}
                   <div>{{item.start_date}} - {{ item.shift_title }}</div>
                {% endfor %}
            {% endfor %}

When I replace “Weeknr” with eg “start_date” things are working.

What does your view look like?

The answer is going to depend upon what the shifts object is that you’re trying to process.

If you’re using the queryset directly, I think that’s not going to work because Weeknr isn’t going to be a field in the elements of the queryset.

You would need to either annotate Weeknr in the query or convert the queryset into a dict and add Weeknr as a key/value to that dict.

Hi Ken, Thanks for being so kind to response to my questions. I just started with Django. Did some basic python course and a ‘Getting Started’ Django’ Youtube course. I’m not at all familiar with queryset and convert into a dict. Can you advise me what road I should follow in order to get familiar with Django app development. I’m a bit impatient and that causes getting stuck like what is happening now. So a good learning path advice would be helpfull.

I always suggest people start out with either or both the Official Django Tutorial and the Django Girls Tutorial. They establish a lot of the necessary fundamentals.

Beyond that, it’s a highly individual decision, based upon what concepts an individual may be struggling with at that point. If there’s anything I’ve learned as a developer, teacher, and mentor, is that there’s no “one size fits all” category of learning materials. Different books resonate with different people.

I do recommed as a “resource of resources” the Awesome Django and Awesome Python pages.

For anything more specific or direct in the way of assistance, you’ll need to post the view. The model is only part of the picture.

Thanks for the suggestions! I will check them out.

Here is my view:

from django.shortcuts import render
from django.http import HttpResponse
from .models import Shift


def index(request):
    shifts = Shift.objects.all()
    return render(request, 'index.html',
                  {'shifts': shifts})

If you are interested here my html tryout what I want to achieve with data

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Simple grid</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
        <link rel="stylesheet" href="./css/simplegrid.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css">

</head>
<body>

<div class="grid-container"><h1>Week 1</h1><!--START WEEK-->

    <div class="grid-container shifts"><!--START SHIFTS-->

        <div class="day1"><!--START DAY-->
            <div class="dayheader">Monday</div>
            <div class="shift">Monday shift</div>
            <div class="shift">Monday shift</div>
            <div class="shift">Monday shift</div>
        </div><!--END DAY-->

        <div class="day2"><!--START DAY-->
            <div class="dayheader">Tuesday</div>
            <div class="shift">Tuesday shift</div>
            <div class="shift">Tuesday shift</div>
        </div><!--END DAY-->

      <div class="day3"><!--START DAY-->
        <div class="dayheader">Wednesday</div>
      </div><!--END DAY-->

        <div class="day4"><!--START DAY-->
            <div class="dayheader">Thursday</div>
            <div class="shift">Thursday shift</div>
            <div class="shift">Thursday shift</div>
            <div class="shift">Thursday shift</div>
            <div class="shift">Thursday shift</div>
            <div class="shift">Thursday shift</div>
        </div><!--END DAY-->

        <div class="day5"><!--START DAY-->
            <div class="dayheader">Friday</div>
        </div><!--END DAY-->

        <div class="day6"><!--START DAY-->
            <div class="dayheader">Saterday</div>
        </div><!--END DAY-->

        <div class="day7"><!--START DAY-->
            <div class="dayheader">Sunday</div>
        </div><!--END DAY-->

    </div><!--END SHIFTS-->

</div><!--END WEEK-->

<div class="grid-container"><h1>Week 2</h1><!--START WEEK-->

    <div class="grid-container shifts"><!--START SHIFTS-->

        <div class="day1"><!--START DAY-->
            <div class="dayheader">Monday</div>
            <div class="shift">Monday shift</div>
            <div class="shift">Monday shift</div>
            <div class="shift">Monday shift</div>
        </div><!--END DAY-->

        <div class="day2"><!--START DAY-->
            <div class="dayheader">Tuesday</div>
            <div class="shift">Tuesday shift</div>
            <div class="shift">Tuesday shift</div>
        </div><!--END DAY-->

      <div class="day3"><!--START DAY-->
        <div class="dayheader">Wednesday</div>
      </div><!--END DAY-->

        <div class="day4"><!--START DAY-->
            <div class="dayheader">Thursday</div>
            <div class="shift">Thursday shift</div>
            <div class="shift">Thursday shift</div>
            <div class="shift">Thursday shift</div>
            <div class="shift">Thursday shift</div>
            <div class="shift">Thursday shift</div>
        </div><!--END DAY-->

        <div class="day5"><!--START DAY-->
            <div class="dayheader">Friday</div>
        </div><!--END DAY-->

        <div class="day6"><!--START DAY-->
            <div class="dayheader">Saterday</div>
        </div><!--END DAY-->

        <div class="day7"><!--START DAY-->
            <div class="dayheader">Sunday</div>
        </div><!--END DAY-->

    </div><!--END SHIFTS-->

</div><!--END WEEK-->

</body>
</html>

And this is the used stylesheet:

body{
  margin: 20px;
}

.grid-container {
  display: grid;
}

.dayheader{
  background-color: darkorange;
  color: #fff;
  padding: 5px;
  margin-bottom: 10px;
}

.shifts{
  grid-template-columns: repeat(7, minmax(0, 1fr));
  grid-gap: 10px;
  margin-bottom: 10px;
}

.shift{
  background-color: #155a9f;
  color: #fff;
  padding: 5px;
  margin-bottom: 10px;
}

@media only screen and (max-width: 1400px) {
  .shifts{
    grid-template-columns: repeat(1, minmax(0, 1fr));
    max-width: 350px;
   }
}

@media screen and (min-width: 1400px) {
  .day1 {grid-column: 1;}
  .day2 {grid-column: 2;}
  .day3 {grid-column: 3;}
  .day4 {grid-column: 4;}
  .day5 {grid-column: 5;}
  .day6 {grid-column: 6;}
  .day7 {grid-column: 7;}
}

So at this point, shifts is a queryset.

Two options:

  • Find the appropriate database function for this, and annotate the Weeknr in the query:

    • Shift.objects.all().annotate(Weeknr=<some database function>)
      Note: Since this work is being done in the database, it’s not capable of using the function that you defined.
  • Return the queryset as a dict and augment the dict with the desired values:

shifts = Shift.objects.all().values()
for a_shift in shifts:
  a_shift['Weeknr'] = ....
1 Like

Hi Ken,

Solved it like this:

{% regroup shifts|dictsort:"start_date" by start_date|date:'W' as newlist %}

Formattted the date in the regroup with |date:‘W’
No need to do this in the model anymore

1 Like

Cool! Glad that’s going to work for you.

I will point out that this isn’t going to be the most efficient way of doing this. Doing “work” in the template is always my last choice - my preference is to do all possible work in the view or database, not the template.

Now, it’s very likely that this is going to be absolutely fine for you. But try to keep this in mind in the future if you find that this page is taking too long to render.

One more thing. Can I add another field to the group header? EG I like to add start_date to the grouper value. I can’t get that working.

{% regroup cities by country as country_list %}

<ul>
{% for country in country_list %}
    <li>{{ country.grouper }} **{{add another field here }}**
    <ul>
        {% for city in country.list %}
          <li>{{ city.name }}: {{ city.population }}</li>
        {% endfor %}
    </ul>
    </li>
{% endfor %}
</ul>

You would need to make sure that that value is being supplied to the template through the context.

I’d need to see the current view to be able to answer your question. Or, it may be easiest for you to just render country_list immediately after the regroup to see what keys are available and under what names.

Can you help me how this render code should look like. This is my real data:

{% regroup shifts by weeknr as week_list %}
    {% render week_list %}?????

I am still struggeling with the regroup because I need a multi level regroup. I would like to try an If else approach to build my html is that a good choice?

To render a variable, you use the “double braces” notation. e.g. {{ week_list }}