Home > Net >  Splitting dictionary objects
Splitting dictionary objects

Time:09-25

I am building a Blog App and I made a queryset which is showing blog date and likes of every day since blog date, But it is showing in dictionary and i am trying to show both instances differently in table like.

Blog Date Likes
20 Sep. 6 Likes
21 Sep. 2 Likes
22 Sep. 4 Likes

But it is showing like :-

({20: 6},{21: 2},{22: 4})

models.py

class BlogPost(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=30, default='')
    date = models.DateTimeField(auto_now_add=True)

class Likes(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    blogpost_like = models.ForeignKey(BlogPost, on_delete=models.CASCADE)

views.py

from django.db.models.functions import ExtractDay
from collections import Counter

def page(request):
    blogpost = get_object_or_404(BlogPost,pk=pk)

    totals = blogpost.likes_set.filter(
        blogpost_like__date=blogpost.date,
        ).annotate(
            date=ExtractDay('blogpost__date'),
        ).values(
            'date'
        ).annotate(
            n=Count('pk')
        ).order_by('date').values()

    results = Counter({d['date']: d['n'] for d in totals})

    context = {'results':results}
    return render(request, 'page.html', context)

What have i tried ? :-

  • I have tried
lists = [{'id': blog.date, 'name': blog.n} for blog in results ]

But it is showing only date like 24 not the likes.

  • than i tried
json.dumps(list(results ))
  • than i tried
from calendar import monthrange

__, ds = monthrange(blogpost.date)
finalSecond = [data[i] for i in range(1, ds 1)]

But it showed

monthrange() missing 1 required positional argument: 'month'

I have tried many times but it is still not working.

Any help would be much Appreciated. Thank You

CodePudding user response:

{d['date']: d['n'] for d in totals}

Makes a dict whose keys are the date and whose vals are the value. Whilst the data can be extracted from this, it doesn't make any sense, particularly as you store them in a list. But you already have nicely structured output in your totals, so use that directly without wrapping it all up in a Counter of dicts (I have no idea why you are using Counter, by the way).

return render(request, 'page.html', {"results": totals})

That way your data is getting through to the template nicely. Then your html template just needs to iterate over results:

{% for result in results %}
<tr>
  <td>result.date</td><td>result.n</td>
</tr>
{% endfor %}

CodePudding user response:

You can use TruncDate to obtain the date:

from django.db.models import Count
from django.db.models.functions import TruncDate

totals = blogpost.likes_set.filter(
    blogpost__date=blogpost.date,
).values(
    date=TruncDate('blogpost__date')
).annotate(
    n=Count('pk')
).order_by('date')

If you pass this to the context, you can render it with:

<table>
  <thead>
    <th>Blog Date</th><th>Likes</th>
  </thead>
  <tbody>
    {% for item in totals %}
      <tr>
        <td>{{ item.date|date:"F, d" }}</td><td>{{ item.n }}</td>
      </tr>
    {% endfor %}
  </tbody>
</table>
  • Related