Использование эквивалента тега django regroup в python

У меня есть проект, построенный на django, в котором я использую шаблонизатор django. Я хочу переключить фронтенд с шаблонизатора django на reactjs. Все работает достаточно хорошо с использованием шаблонизатора django. Я гуглил и переполнял стек везде, но не нашел решения моей проблемы. Вот что я сделал, используя шаблонизатор django (все работает хорошо):

# models.py

class Post(models.Model):
    ...
    publish = models.DateTimeField(
        default=timezone.now,
        verbose_name=("Publication date"),
    )
    ...

Мой templatetag выглядит следующим образом:

# blog_tags.py

@register.inclusion_tag('blog/month_links_snippet.html')
def render_month_links():
    all_posts = Post.published.dates('publish', 'month', order='DESC')
    return {'all_posts': all_posts,}

Мой файл шаблона выглядит следующим образом:

# blog/month_links_snippet.html

{% regroup all_posts by year as dates_by_year %}
<div class="sidebar">
    <ul class="active list-unstyled">
    {% for month in dates_by_year %}
        <li id="year{{ month.grouper }}"{% if forloop.first %} class="active"{% endif %}>
        <h2 style="font-size: 18px"><a href="{% url 'blog:archive-year' month.grouper %}">{{ month.grouper }}</a> <i class="collapsing-icon fa fa-plus"></i></h2>
        <div class="collapsing-content">
            <ul class="list-unstyled">
            {% for d in month.list %}
                <li><a href="{% url 'blog:archive_month_numeric' d|date:"Y" d|date:"n" %}">{{ d|date:"F Y" }}</a></li>
            {% endfor %}
            </ul>
        </div>
        </li>
    {% endfor %}
    </ul>
</div>

Все работает так, как ожидалось. Посмотрите:

Архив записей в блоге

Как я могу достичь этого, используя django rest framework?

Помните, что эти данные позже будут потребляться reactjs.

Вот методы, которые я пробовал до сих пор с DRF

Метод 1

# models.py

class Post(models.Model):
    ...
    publish = models.DateTimeField(
        default=timezone.now,
        verbose_name=("Publication date"),
    )
    ...
    
    def date(self):
        return self.publish.strftime("%Y-%m-%d")

Мой модуль сериализаторов выглядит следующим образом:

# serializers.py

class PostArchiveSidebarSerializer(serializers.ModelSerializer):
    publish = serializers.DateTimeField(format="%Y")
    date= serializers.SerializerMethodField(source="date")
    class Meta: 
        model = Post
        fields = ["publish", "date"]

    def get_date(self, obj):
        return obj.date()

Мой модуль представлений выглядит следующим образом:

from itertools import groupby
from operator import itemgetter
@api_view(["GET"])
def year_month_archive(request):
    # published = PublishedManager() my custom manager.
    posts = Post.published.filter(status='published').order_by('-publish')
    serializer = PostArchiveSidebarSerializer(posts, many=True)
    grouped = groupby(serializer.data, itemgetter('date'))
    new_data = {k:next(v) for k, v in grouped}
    # I use the next() func to make the month unique for a specific year
    return Response(new_data)

Выход метода 1

{
    "2021-08-31": {
        "publish": "2021",
        "date": "2021-08-31"
    },
    "2020-12-05": {
        "publish": "2020",
        "date": "2020-12-05"
    },
    "2020-05-17": {
        "publish": "2020",
        "date": "2020-05-17"
    },
    "2020-04-06": {
        "publish": "2020",
        "date": "2020-04-06"
    },
    "2020-03-12": {
        "publish": "2020",
        "date": "2020-03-12"
    },
    "2020-02-09": {
        "publish": "2020",
        "date": "2020-02-09"
    },
    "2019-09-13": {
        "publish": "2019",
        "date": "2019-09-13"
    }
}

Метод 2

# models.py

class Post(models.Model):
    ...
    publish = models.DateTimeField(
        default=timezone.now,
        verbose_name=("Publication date"),
    )
    ...
    

Здесь не нужны сериализаторы

# views.py

from collections import defaultdict, Counter
from django.template.defaultfilters import date

@api_view(["GET"])
def year_month_archive(request):
    year_frequency = defaultdict(int)
    all_posts = Post.published.dates("publish", "month", order="DESC")
    for year in all_posts:
        format_month = date(year, 'F Y')
        year_frequency[year.year] += 1
        year_frequency[format_month] += 1
    count_year = list(Counter(year_frequency))

    return Response({'archive': count_year})

Выход метода 2

{
    "archive": [
        2021,
        "August 2021",
        2020,
        "December 2020",
        "May 2020",
        "April 2020",
        "March 2020",
        "February 2020",
        2019,
        "September 2019"
    ]
}

Моя цель - создать аккордеон с годом 2021 в качестве заголовка и August 2021 в качестве содержимого.

Любая помощь будет высоко оценена.

Заранее спасибо

Это мой первый вопрос здесь 😁

Вернуться на верх