Stuck to apply authentication system.

I am trying to add authentication app to my project. But, when I logout, there is no user logged in. So, the page doesn’t get rendered itself, which is a problem. My page has a form to add a new expense and I want to only add a new expense when a user is logged in. But at the same time I don’t want new visitors to show nothing. Users should be able to see the page without logged in but cannot add expenses. How can I do this? Or should I completely rethink this approach?

The error in page:-

TypeError at /
Field 'id' expected a number but got <SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x000001AF8AB8FF70>>.
Request Method:	GET
Request URL:	http://127.0.0.1:8000/
Django Version:	5.0
Exception Type:	TypeError
Exception Value:	
Field 'id' expected a number but got <SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x000001AF8AB8FF70>>.
Exception Location:	D:\PRATEEK\Django Projects\money_env\lib\site-packages\django\db\models\fields\__init__.py, line 2114, in get_prep_value
Raised during:	expenses.views.IndexView
Python Executable:	D:\PRATEEK\Django Projects\money_env\Scripts\python.exe
Python Version:	3.10.5
Python Path:	
['D:\\PRATEEK\\Django Projects\\money_env\\money',
 'C:\\Users\\MI\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip',
 'C:\\Users\\MI\\AppData\\Local\\Programs\\Python\\Python310\\DLLs',
 'C:\\Users\\MI\\AppData\\Local\\Programs\\Python\\Python310\\lib',
 'C:\\Users\\MI\\AppData\\Local\\Programs\\Python\\Python310',
 'D:\\PRATEEK\\Django Projects\\money_env',
 'D:\\PRATEEK\\Django Projects\\money_env\\lib\\site-packages']
Server time:	Sun, 10 Dec 2023 18:38:50 +0000

views.py:-

from django.shortcuts import render, redirect
from django.urls import reverse_lazy
from django.views.generic import View, UpdateView, DeleteView
from .forms import ExpenseForm
from .models import Expense
from django.db.models import Sum, DateTimeField
import datetime
from django.db.models.functions import TruncDate

# Create your views here.
class IndexView(View):
    template_name = 'expenses/index.html'

    def get(self, request):
        expense_form = ExpenseForm()
        expenses = Expense.objects.filter(user=request.user)
        total_expenses = Expense.objects.filter(user=request.user).aggregate(Sum('amount'))

        today = datetime.date.today()
        # last year sum
        last_year = today - datetime.timedelta(days=365)
        yearly_sum = Expense.objects.filter(date__gt=last_year, user=request.user).aggregate(Sum('amount'))

        # last month sum
        last_month = today - datetime.timedelta(days=30)
        monthly_sum = Expense.objects.filter(date__gt=last_month, user=request.user).aggregate(Sum('amount'))

        # last week sum
        last_week = today - datetime.timedelta(days=7)
        weekly_sum = Expense.objects.filter(date__gt=last_week, user=request.user).aggregate(Sum('amount'))

        year_start = datetime.date(today.year, 1, 1)
        month_start = datetime.date(today.year, today.month, 1)
        week_start = today - datetime.timedelta(days=today.weekday())

        # sums from since starting of...
        this_year_sum = Expense.objects.filter(date__gt=year_start, user=request.user).aggregate(Sum('amount'))
        this_month_sum = Expense.objects.filter(date__gt=month_start, user=request.user).aggregate(Sum('amount'))
        this_week_sum = Expense.objects.filter(date__gt=week_start, user=request.user).aggregate(Sum('amount'))

        daily_sums = Expense.objects.filter(user=request.user).annotate(
            truncated_date=TruncDate('date', output_field=DateTimeField())
        ).values('truncated_date').annotate(sum=Sum('amount')).order_by('-truncated_date')

        categorical_sums = Expense.objects.filter(user=request.user).values('category').annotate(sum=Sum('amount'))

        return render(request, self.template_name, {
            'expense_form': expense_form,
            'expenses': expenses,
            'total_expenses': total_expenses,
            'yearly_sum': yearly_sum,
            'monthly_sum': monthly_sum,
            'weekly_sum': weekly_sum,
            'this_year_sum': this_year_sum,
            'this_month_sum': this_month_sum,
            'this_week_sum': this_week_sum,
            'daily_sums': daily_sums,
            'categorical_sums': categorical_sums,
        })
    
    def post(self, request):
        expense_form = ExpenseForm(request.POST)
        if expense_form.is_valid():
            expense = expense_form.save(commit=False)
            expense.user = request.user
            expense.save()
            return redirect('expenses:index')
        expenses = Expense.objects.all()
        return render(request, self.template_name, {'expense_form': expense_form, 'expenses': expenses})

class ExpenseUpdateView(UpdateView):
    model = Expense
    fields = ['name', 'amount', 'category']
    template_name_suffix = '_update_form'
    success_url = reverse_lazy('expenses:index')

class ExpenseDeleteView(DeleteView):
    model = Expense
    success_url = reverse_lazy('expenses:index')

If the requesting browser isn’t logged in, then request.user is the AnonymousUser. (Also see is_authenticated)

Also see Limiting access to logged-in users for some examples of ways to handle this.

Can I handle this with the @login_required decorator?