If you’re building a nutrition app, one of the most useful features you can add is a daily nutrition check-in. It gives users a simple way to log whether they followed their meal plan, drank enough water, and met their calorie target.
In this tutorial, I’ll show you how to build a Daily Nutrition Check-in feature in Django REST Framework. We’ll also connect it to a streak system so the app can reward consistency.
What we’ll build
By the end of this guide, you’ll have:
- a
DailyNutritionCheckInmodel - a serializer for the API
- an authenticated API endpoint
- streak tracking with
UserStreak - a clean route users can call from the frontend
Prerequisites
Before you begin, make sure you already have:
- Django installed
- Django REST Framework installed
- a Django project with authentication set up
- a nutrition app where you can add models and views
Step 1: Create the model
We need a model that stores one nutrition check-in per user per day.
Add this to your models.py:
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}"
Why this model works
The most important part here is:
unique_together = ('user', 'log_date')
That ensures each user can only have one check-in per day. It prevents duplicate entries and keeps your data clean.
Step 2: Add a streak model
If your app already has streak tracking, you can reuse it. If not, add this model:
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"
Why this is useful
This lets your app track:
- the user’s current streak
- their longest streak
- the date they last completed a check-in
That means the app can motivate users to stay consistent.
Step 3: Create the serializer
Now we need to expose the model through the API.
Add this to serializers.py:
from rest_framework import serializers
from .models import DailyNutritionCheckIn
class DailyNutritionCheckInSerializer(serializers.ModelSerializer):
class Meta:
model = DailyNutritionCheckIn
fields = '__all__'
read_only_fields = ('user', 'created_at')
Why mark fields as read-only?
We do not want the client to set:
usercreated_at
Those should be controlled by the backend for security and consistency.
Step 4: Build the API view
Now let’s create the endpoint that saves the check-in and updates the streak.
Add this to views.py:
from datetime import timedelta
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
from .serializers import DailyNutritionCheckInSerializer
class DailyNutritionCheckInView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
serializer = DailyNutritionCheckInSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
checkin = serializer.save(user=request.user)
log_date = checkin.log_date
streak, created = UserStreak.objects.get_or_create(
user=request.user,
defaults={
'current_streak': 1,
'longest_streak': 1,
'last_logged_date': log_date
}
)
if not created and streak.last_logged_date != log_date:
if streak.last_logged_date == log_date - timedelta(days=1):
streak.current_streak += 1
else:
streak.current_streak = 1
if streak.current_streak > streak.longest_streak:
streak.longest_streak = streak.current_streak
streak.last_logged_date = log_date
streak.save()
return Response({
"message": "Daily check-in saved successfully.",
"checkin": DailyNutritionCheckInSerializer(checkin).data,
"current_streak": streak.current_streak,
"longest_streak": streak.longest_streak
}, status=status.HTTP_201_CREATED)
How the streak logic works
The logic is simple:
- if the user checked in yesterday, increase the streak
- if they missed a day, reset the streak
- update the longest streak if the current one beats it
This is a good baseline for gamification in a nutrition app.
Step 5: Add the URL route
Now register the endpoint in urls.py:
from django.urls import path
from .views import DailyNutritionCheckInView
urlpatterns = [
path('api/check-in/', DailyNutritionCheckInView.as_view(), name='daily-checkin'),
]
Step 6: Test the endpoint
Here’s an example request body you can send to the API:
{
"breakfast_completed": true,
"lunch_completed": true,
"dinner_completed": false,
"water_intake_ml": 1800,
"met_calorie_target": true,
"notes": "Healthy day overall."
}
Expected response
You should get a response like this:
{
"message": "Daily check-in saved successfully.",
"checkin": {
"id": 1,
"user": 3,
"log_date": "2025-06-01",
"breakfast_completed": true,
"lunch_completed": true,
"dinner_completed": false,
"water_intake_ml": 1800,
"met_calorie_target": true,
"notes": "Healthy day overall.",
"created_at": "2025-06-01T10:30:00Z"
},
"current_streak": 4,
"longest_streak": 7
}
Common improvements you can add later
Once the basic feature works, you can improve it by adding:
- edit/update support for same-day check-ins
- badge rewards for streak milestones
- daily reminders
- weekly progress summaries
- charts for water intake and meal completion
Conclusion
A daily nutrition check-in is a simple feature, but it adds a lot of value to a meal-planning app. It helps users stay accountable, gives them visible progress, and makes the app feel more engaging.
With Django REST Framework, this feature is straightforward to build using:
- a model for storing logs
- a serializer for API validation
- an authenticated API view
- streak tracking for motivation
If you’re building a nutrition app, this is a great feature to add early because it creates a strong foundation for gamification and habit tracking.
Top comments (0)