DEV Community

Cover image for From Check-Ins to Insights: Building a Weekly Nutrition Summary API in Django REST Framework
ugbotu eferhire
ugbotu eferhire

Posted on

From Check-Ins to Insights: Building a Weekly Nutrition Summary API in Django REST Framework

Nutrition apps are evolving.

What used to be a simple meal log or calorie counter is now becoming something much more useful: a system that helps people understand their habits, stay consistent, and make better decisions over time.

That shift matters.

A single check-in tells you what happened today.

A weekly summary tells you whether behavior is actually changing.

In this article, we’ll build a Weekly Nutrition Summary API in Django REST Framework. The goal is not just to count records, but to turn daily nutrition logs into actionable insight.

By the end, you’ll have an endpoint that gives users a clear weekly view of:

  • how many days they checked in
  • how many meals they completed
  • how much water they drank
  • how often they met their calorie target
  • their current and longest streaks
  • a daily breakdown for dashboards and charts

This is the kind of feature that makes a nutrition app feel more like a product and less like a form.

Why this feature matters

Most health and habit-tracking apps collect data, but too few translate that data into meaningful feedback.

That’s the difference between logging and learning.

A weekly summary layer gives your app:

  • better retention
  • stronger user engagement
  • more useful progress tracking
  • a foundation for charts, gamification, and recommendations

It also creates a cleaner product story:

Users don’t just check in — they get insight back.

What we’ll build

We’ll assume you already have:

  • a DailyNutritionCheckIn model
  • a UserStreak model
  • authentication set up in Django REST Framework

We’ll build:

  • a weekly summary API view
  • a route for the endpoint
  • a response structure that supports both dashboards and analytics

Step 1: Make sure your daily nutrition log exists

The weekly summary depends on daily data. If you don’t already have a check-in model, here’s a clean version to build from:

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone

class DailyNutritionCheckIn(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='nutrition_checkins')
    log_date = models.DateField(default=timezone.localdate)
    breakfast_completed = models.BooleanField(default=False)
    lunch_completed = models.BooleanField(default=False)
    dinner_completed = models.BooleanField(default=False)
    water_intake_ml = models.PositiveIntegerField(default=0)
    met_calorie_target = models.BooleanField(default=False)
    notes = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('user', 'log_date')
        ordering = ['-log_date']

    def __str__(self):
        return f"{self.user.username} - {self.log_date}"
Enter fullscreen mode Exit fullscreen mode

Why this structure works

This model gives you one record per user per day. That is important because a summary layer works best when the underlying data is normalized and predictable.

The unique_together constraint prevents duplicate daily logs, which keeps weekly calculations accurate.


Step 2: Keep streak tracking in place

If you already have a streak model, reuse it. If not, you can use this:

class UserStreak(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='streak')
    current_streak = models.PositiveIntegerField(default=1)
    longest_streak = models.PositiveIntegerField(default=1)
    last_logged_date = models.DateField(default=timezone.localdate)

    def __str__(self):
        return f"{self.user.username} - {self.current_streak} Day Streak"
Enter fullscreen mode Exit fullscreen mode

Why this matters

Streaks help turn passive tracking into habit formation.

A weekly summary becomes more powerful when it includes:

  • consistency metrics
  • progress indicators
  • habit momentum

That’s what keeps users coming back.


Step 3: Build the weekly summary view

Now we’ll create the API endpoint that reads the past 7 days of check-ins and returns a structured summary.

Add this to views.py:

from datetime import timedelta
from django.utils import timezone
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status

from .models import DailyNutritionCheckIn, UserStreak


class WeeklyNutritionSummaryView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        today = timezone.localdate()
        week_start = today - timedelta(days=6)

        checkins = DailyNutritionCheckIn.objects.filter(
            user=request.user,
            log_date__range=[week_start, today]
        ).order_by('log_date')

        streak, _ = UserStreak.objects.get_or_create(user=request.user)

        breakfast_count = checkins.filter(breakfast_completed=True).count()
        lunch_count = checkins.filter(lunch_completed=True).count()
        dinner_count = checkins.filter(dinner_completed=True).count()
        calorie_target_count = checkins.filter(met_calorie_target=True).count()

        total_water = sum(checkin.water_intake_ml for checkin in checkins)
        average_water = round(total_water / checkins.count(), 2) if checkins.exists() else 0

        daily_summary = [
            {
                "log_date": checkin.log_date,
                "breakfast_completed": checkin.breakfast_completed,
                "lunch_completed": checkin.lunch_completed,
                "dinner_completed": checkin.dinner_completed,
                "water_intake_ml": checkin.water_intake_ml,
                "met_calorie_target": checkin.met_calorie_target,
                "notes": checkin.notes,
            }
            for checkin in checkins
        ]

        return Response({
            "week_start": week_start,
            "week_end": today,
            "checkins_count": checkins.count(),
            "breakfast_completed_count": breakfast_count,
            "lunch_completed_count": lunch_count,
            "dinner_completed_count": dinner_count,
            "calorie_target_days": calorie_target_count,
            "total_water_intake_ml": total_water,
            "average_water_intake_ml": average_water,
            "current_streak": streak.current_streak,
            "longest_streak": streak.longest_streak,
            "daily_summary": daily_summary,
        }, status=status.HTTP_200_OK)
Enter fullscreen mode Exit fullscreen mode

Step 4: Understand the logic

This view does three important things:

1. It defines a fixed 7-day window

today = timezone.localdate()
week_start = today - timedelta(days=6)
Enter fullscreen mode Exit fullscreen mode

This ensures the summary always covers the last 7 days, including today.

2. It pulls only the authenticated user’s logs

checkins = DailyNutritionCheckIn.objects.filter(
    user=request.user,
    log_date__range=[week_start, today]
)
Enter fullscreen mode Exit fullscreen mode

That means the summary is private and personalized.

3. It converts raw logs into useful metrics

Instead of returning raw database rows only, it computes:

  • meal completion counts
  • calorie target days
  • total hydration
  • average hydration
  • streak data

That’s the move from data collection to insight delivery.


Step 5: Add the URL route

Next, connect the view in your urls.py:

from django.urls import path
from .views import WeeklyNutritionSummaryView

urlpatterns = [
    path('api/weekly-summary/', WeeklyNutritionSummaryView.as_view(), name='weekly-summary'),
]
Enter fullscreen mode Exit fullscreen mode

Step 6: Example response

Here’s what the API response might look like:

{
  "week_start": "2025-06-01",
  "week_end": "2025-06-07",
  "checkins_count": 5,
  "breakfast_completed_count": 4,
  "lunch_completed_count": 5,
  "dinner_completed_count": 3,
  "calorie_target_days": 4,
  "total_water_intake_ml": 9200,
  "average_water_intake_ml": 1840,
  "current_streak": 5,
  "longest_streak": 8,
  "daily_summary": [
    {
      "log_date": "2025-06-01",
      "breakfast_completed": true,
      "lunch_completed": true,
      "dinner_completed": false,
      "water_intake_ml": 1800,
      "met_calorie_target": true,
      "notes": "Good day"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Why this response format is useful

This response is intentionally split into two layers:

  • summary metrics
  • daily breakdown

That makes it flexible enough for:

  • dashboard cards
  • progress bars
  • charts
  • habit calendars
  • mobile app views

A good API should not only answer a question.

It should give the frontend enough structure to build a useful experience.


Step 7: Improve it with aggregation later

The version above is clear and readable, which is great for a first implementation.

If you want to optimize it later, you can move more of the computation into database-level aggregation using:

  • Count
  • Sum
  • Avg

That becomes useful if your dataset grows or if you expect many users to hit the summary endpoint frequently.

Example:

from django.db.models import Count, Sum, Avg
Enter fullscreen mode Exit fullscreen mode

This allows the database to do more work instead of Python looping through the records.

For most early-stage apps, the simpler implementation is perfectly fine.


Step 8: Think about product value, not just code

This feature is more than a backend endpoint.

It changes how your app communicates value.

A weekly nutrition summary helps users answer questions like:

  • Am I staying consistent?
  • Which meals do I skip most often?
  • Am I drinking enough water?
  • Is my streak improving?
  • What does my week actually look like?

That kind of feedback is what turns an app into a habit engine.

From a product perspective, that’s important because insight creates stickiness.


Optional next steps

Once this feature is in place, you can extend it in a few strong directions:

Add caching

Cache the weekly summary briefly to reduce repeated computation.

Add charts

Use the daily breakdown for line charts, bar charts, or a weekly heatmap.

Add badge logic

Reward users for:

  • 7-day streaks
  • full hydration weeks
  • consistent meal completion

Add recommendations

Use the weekly summary to suggest:

  • better hydration habits
  • meal timing improvements
  • smarter calorie planning

That’s where the app starts feeling intelligent.


Conclusion

Building a weekly nutrition summary is one of those features that sounds small but changes the product in a meaningful way.

Instead of just collecting check-ins, your app starts turning behavior into insight.

That matters because the best health apps don’t just ask users to log data. They help users understand themselves better.

With Django REST Framework, the implementation is straightforward:

  • model your daily logs
  • track streaks
  • create a summary API
  • return both totals and daily breakdowns

That gives you a strong foundation for dashboards, motivation, and future intelligence features.

If you’re building a nutrition or habit-tracking app, this is a feature worth adding early.

Top comments (0)