Django待办应用需求:为每个用户分配专属独立待办列表
Got it, let's walk through how to add user-specific todo lists to your Django app—you’ve already got the core CRUD and auth set up, so this is just a few key tweaks:
First, you need to update your Todo model to associate each task with a specific user. Add a foreign key field that connects to Django's built-in User model:
# models.py from django.db import models from django.contrib.auth.models import User class Todo(models.Model): title = models.CharField(max_length=200) description = models.TextField(blank=True) completed = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) # Add this field to tie todos to a user user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='todos') def __str__(self): return self.title
on_delete=models.CASCADEensures that if a user is deleted, all their todos are removed too.related_name='todos'lets you easily access a user's todos later (likerequest.user.todos.all()).
Next, you’ll modify your views to only show the current user’s todos, and automatically assign new todos to the logged-in user. Also, add login protection so only authenticated users can access todo features:
# views.py from django.shortcuts import render, redirect, get_object_or_404 from .models import Todo from .forms import TodoForm from django.contrib.auth.decorators import login_required # Require login for all todo views @login_required def todo_list(request): # Only fetch todos belonging to the current user todos = Todo.objects.filter(user=request.user) return render(request, 'todo/todo_list.html', {'todos': todos}) @login_required def todo_create(request): if request.method == 'POST': form = TodoForm(request.POST) if form.is_valid(): # Save the form without committing to DB first todo = form.save(commit=False) # Assign the current user to the todo todo.user = request.user todo.save() return redirect('todo_list') else: form = TodoForm() return render(request, 'todo/todo_form.html', {'form': form}) @login_required def todo_update(request, pk): # Only let users access their own todos via URL todo = get_object_or_404(Todo, pk=pk, user=request.user) if request.method == 'POST': form = TodoForm(request.POST, instance=todo) if form.is_valid(): form.save() return redirect('todo_list') else: form = TodoForm(instance=todo) return render(request, 'todo/todo_form.html', {'form': form}) @login_required def todo_delete(request, pk): # Same check for deletion—only allow users to delete their own todos todo = get_object_or_404(Todo, pk=pk, user=request.user) if request.method == 'POST': todo.delete() return redirect('todo_list') return render(request, 'todo/todo_confirm_delete.html', {'todo': todo})
@login_requiredredirects unauthenticated users to the login page.filter(user=request.user)ensures only the current user's todos are displayed.get_object_or_404(..., user=request.user)prevents users from accessing others' todos by tampering with URLs.
You don’t want users to select which user a todo belongs to—so exclude the user field from your form:
# forms.py from django import forms from .models import Todo class TodoForm(forms.ModelForm): class Meta: model = Todo # Exclude the user field so it doesn't appear in the form exclude = ['user', 'created_at'] # Alternatively, list only the fields you want to show: # fields = ['title', 'description', 'completed']
Since you modified the Todo model, generate and apply migrations to update your database:
python manage.py makemigrations python manage.py migrate
If you have existing todos, you’ll be prompted to set a default user for them—you can pick your superuser or skip if you don’t need old data.
- Log in with different user accounts to confirm each only sees their own todos.
- Try accessing another user’s todo via URL (e.g., change the
pkin the edit/delete URL) — you should get a 404 error. - Verify unlogged users can’t access any todo pages.
That’s it! Your app now has fully isolated todo lists for each user.
内容的提问来源于stack exchange,提问作者Zelda

