Updating object IntegrityError, NOT NULL constraint failed

I’m trying to create view for my Food Tracking App where I can first pick a given date and then add items to the FoodLog object, however while viewing macros work after picking date, I can’t really add any new other objects becuase of the following error:

django.db.utils.IntegrityError: NOT NULL constraint failed: accounts_foodlogfooditem.food_log_id
[23/Sep/2023 13:56:08] “POST /accounts/food-log/ HTTP/1.1” 500 153768

I want to make it so that first I’ll be able to pick a date and then either show what’s in the FoodLog or be able to add new objects to it.

My View:

def food_log(request):
food_log = None
total_macros = {}

if request.method == 'POST':
    date_form = DateForm(request.POST)
    food_item_form = FoodLogFoodItemForm(request.POST)

    if date_form.is_valid():
        selected_date = date_form.cleaned_data['date']
        food_log, created = FoodLog.objects.get_or_create(user=request.user, date=selected_date)
        total_macros = food_log.calculate_total_macros_log()

    if food_item_form.is_valid():
        food_log_food_item = food_item_form.save(commit=False)
        food_log_food_item.food_log = food_log
        food_log_food_item.save()

else:
    today = timezone.now().date()
    food_log = FoodLog.objects.filter(user=request.user, date=today).first()
    date_form = DateForm(initial={'date': today})

    if food_log:
        total_macros = food_log.calculate_total_macros_log()

food_item_form = FoodLogFoodItemForm()

return render(request, 'food_log.html',
              {'food_log': food_log, 'date_form': date_form, 'food_item_form': food_item_form,
               'total_macros': total_macros})

Models I have:

class FoodLog(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
foods = models.ManyToManyField(FoodItem, blank=True, through="FoodLogFoodItem")
meals = models.ManyToManyField(Meal, blank=True, through="FoodLogMeal")
date = models.DateField()

def calculate_total_macros_log(self):
    log_total_kcal = 0
    log_total_carbohydrates = 0
    log_total_fats = 0
    log_total_proteins = 0

    # Calories and macronutrients from FoodLogFoodItem - divided by 100 as FoodItems have values per 100g
    for food_log_food_item in self.foodlogfooditem_set.all():
        food_item = food_log_food_item.food_item
        quantity = food_log_food_item.quantity
        log_total_kcal += food_item.kcal * quantity/100
        log_total_carbohydrates += food_item.carbohydrates * quantity/100
        log_total_fats += food_item.fats * quantity/100
        log_total_proteins += food_item.proteins * quantity/100

    # Calories and macronutrients from FoodLogMeal - divided by 100 as Meals have values per 100g
    for food_log_meal in self.foodlogmeal_set.all():
        meal = food_log_meal.meal
        meal_macros = meal.calculate_total_macros_meal()
        quantity = food_log_meal.quantity
        log_total_kcal += meal_macros['total_kcal_per_100g'] * quantity/100
        log_total_carbohydrates += meal_macros['total_carbohydrates_per_100g'] * quantity/100
        log_total_fats += meal_macros['total_fats_per_100g'] * quantity/100
        log_total_proteins += meal_macros['total_proteins_per_100g'] * quantity/100

    return {
        'log_total_kcal': log_total_kcal,
        'log_total_carbohydrates': log_total_carbohydrates,
        'log_total_fats': log_total_fats,
        'log_total_proteins': log_total_proteins,
    }

def __str__(self):
    return f"{self.user.username}'s Food Log - {self.date}"


class FoodLogFoodItem(models.Model):
food_log = models.ForeignKey(FoodLog, on_delete=models.CASCADE)
food_item = models.ForeignKey(FoodItem, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=1)

class FoodLogMeal(models.Model):
food_log = models.ForeignKey(FoodLog, on_delete=models.CASCADE)
meal = models.ForeignKey(Meal, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=1)

Forms:

class DateForm(forms.Form):
date = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'}))

def __init__(self, *args, **kwargs):
    initial_date = kwargs.pop('initial_date', None)
    super().__init__(*args, **kwargs)
    if initial_date:
        self.fields['date'].initial = initial_date


class FoodLogFoodItemForm(forms.ModelForm):
    class Meta:
        model = FoodLogFoodItem
        fields = ['food_item', 'quantity']


class FoodLogMealForm(forms.ModelForm):
    class Meta:
        model = FoodLogMeal
        fields = ['meal', 'quantity']

Leave a Comment