I have a project built with django whereby I use django's template engine. I want to switch the frontend from django template engine to reactjs. Everything works quite well using django template engine. I have googled and stackoverflowed everywhere but no solution to my problem. Here is what I did using django template engine (everything works well):
# models.py
class Post(models.Model):
...
publish = models.DateTimeField(
default=timezone.now,
verbose_name=("Publication date"),
)
...
My templatetag looks like this:
# 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,}
My template file looks like this:
# 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>
Everything works as expected. Take a look:
How can I achieve this using django rest framework?
Please remember that this data will later be consumed by reactjs.
These are the methods that I have tried so far with DRF
Method 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")
My serializers module looks like this:
# 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()
My views module looks like this:
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)
Method 1 output
{
"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"
}
}
Method 2
# models.py
class Post(models.Model):
...
publish = models.DateTimeField(
default=timezone.now,
verbose_name=("Publication date"),
)
...
No serializers needed here
# 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})
Method 2 output
{
"archive": [
2021,
"August 2021",
2020,
"December 2020",
"May 2020",
"April 2020",
"March 2020",
"February 2020",
2019,
"September 2019"
]
}
My goal is to create an accordion with year 2021 as the title and August 2021 as the content.
Any help will be highly appreciated.
Thanks in advance
This is my first question in here