实操 Todo List应用
一、今日学习内容概述
学习模块 | 重要程度 | 预计学时 | 主要内容 |
---|---|---|---|
项目初始化 | ⭐⭐⭐⭐ | 0.5小时 | 创建项目、配置环境 |
模型设计 | ⭐⭐⭐⭐⭐ | 1小时 | Todo模型设计与实现 |
CRUD视图 | ⭐⭐⭐⭐⭐ | 2小时 | 实现增删改查功能 |
模板开发 | ⭐⭐⭐⭐ | 1.5小时 | 页面布局与交互设计 |
功能测试 | ⭐⭐⭐ | 1小时 | 功能测试与调试 |
二、项目初始化
2.1 创建项目和应用
# 创建项目
django-admin startproject todoproject# 进入项目目录
cd todoproject# 创建应用
python manage.py startapp todos
2.2 配置项目
# todoproject/settings.pyINSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','todos.apps.TodosConfig', # 添加todos应用
]# 配置时区和语言
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
三、模型设计
3.1 创建Todo模型
# todos/models.py
from django.db import models
from django.contrib.auth.models import Userclass Todo(models.Model):PRIORITY_CHOICES = [('high', '高'),('medium', '中'),('low', '低'),]title = models.CharField('标题', max_length=200)description = models.TextField('描述', blank=True)created_date = models.DateTimeField('创建时间', auto_now_add=True)due_date = models.DateTimeField('截止时间', null=True, blank=True)completed = models.BooleanField('是否完成', default=False)priority = models.CharField('优先级', max_length=6, choices=PRIORITY_CHOICES, default='medium')user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')class Meta:ordering = ['-created_date']verbose_name = '待办事项'verbose_name_plural = verbose_namedef __str__(self):return self.title
3.2 创建表单类
# todos/forms.py
from django import forms
from .models import Todoclass TodoForm(forms.ModelForm):class Meta:model = Todofields = ['title', 'description', 'due_date', 'priority']widgets = {'title': forms.TextInput(attrs={'class': 'form-control'}),'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),'due_date': forms.DateTimeInput(attrs={'class': 'form-control','type': 'datetime-local'}),'priority': forms.Select(attrs={'class': 'form-control'}),}
四、CRUD视图实现
4.1 视图代码
# todos/views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .models import Todo
from .forms import TodoForm@login_required
def todo_list(request):todos = Todo.objects.filter(user=request.user)return render(request, 'todos/todo_list.html', {'todos': todos})@login_required
def todo_create(request):if request.method == 'POST':form = TodoForm(request.POST)if form.is_valid():todo = form.save(commit=False)todo.user = request.usertodo.save()messages.success(request, '待办事项创建成功!')return redirect('todo_list')else:form = TodoForm()return render(request, 'todos/todo_form.html', {'form': form, 'title': '创建待办事项'})@login_required
def todo_update(request, pk):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()messages.success(request, '待办事项更新成功!')return redirect('todo_list')else:form = TodoForm(instance=todo)return render(request, 'todos/todo_form.html', {'form': form, 'title': '编辑待办事项'})@login_required
def todo_delete(request, pk):todo = get_object_or_404(Todo, pk=pk, user=request.user)if request.method == 'POST':todo.delete()messages.success(request, '待办事项删除成功!')return redirect('todo_list')return render(request, 'todos/todo_confirm_delete.html', {'todo': todo})@login_required
def todo_toggle_complete(request, pk):todo = get_object_or_404(Todo, pk=pk, user=request.user)todo.completed = not todo.completedtodo.save()return redirect('todo_list')
4.2 URL配置
# todoproject/urls.py
from django.contrib import admin
from django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('', include('todos.urls')),
]# todos/urls.py
from django.urls import path
from . import viewsurlpatterns = [path('', views.todo_list, name='todo_list'),path('create/', views.todo_create, name='todo_create'),path('update/<int:pk>/', views.todo_update, name='todo_update'),path('delete/<int:pk>/', views.todo_delete, name='todo_delete'),path('toggle/<int:pk>/', views.todo_toggle_complete, name='todo_toggle_complete'),
]
五、模板开发
5.1 基础模板
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="zh-hans">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>{% block title %}Todo List{% endblock %}</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body><nav class="navbar navbar-expand-lg navbar-dark bg-dark"><div class="container"><a class="navbar-brand" href="{% url 'todo_list' %}">Todo List</a><div class="collapse navbar-collapse"><ul class="navbar-nav ms-auto">{% if user.is_authenticated %}<li class="nav-item"><span class="nav-link">{{ user.username }}</span></li><li class="nav-item"><a class="nav-link" href="{% url 'logout' %}">退出</a></li>{% else %}<li class="nav-item"><a class="nav-link" href="{% url 'login' %}">登录</a></li>{% endif %}</ul></div></div></nav><div class="container mt-4">{% if messages %}{% for message in messages %}<div class="alert alert-{{ message.tags }}">{{ message }}</div>{% endfor %}{% endif %}{% block content %}{% endblock %}</div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
5.2 列表页面
<!-- templates/todos/todo_list.html -->
{% extends 'base.html' %}{% block content %}
<div class="row mb-4"><div class="col"><h2>我的待办事项</h2></div><div class="col text-end"><a href="{% url 'todo_create' %}" class="btn btn-primary">添加待办事项</a></div>
</div><div class="row"><div class="col">{% if todos %}<div class="list-group">{% for todo in todos %}<div class="list-group-item {% if todo.completed %}bg-light{% endif %}"><div class="d-flex justify-content-between align-items-center"><div><h5 class="mb-1 {% if todo.completed %}text-decoration-line-through{% endif %}">{{ todo.title }}</h5><p class="mb-1">{{ todo.description }}</p><small>优先级: {{ todo.get_priority_display }} |创建时间: {{ todo.created_date|date:"Y-m-d H:i" }}{% if todo.due_date %}| 截止时间: {{ todo.due_date|date:"Y-m-d H:i" }}{% endif %}</small></div><div><form action="{% url 'todo_toggle_complete' todo.pk %}" method="post" class="d-inline">{% csrf_token %}<button type="submit" class="btn btn-sm btn-{% if todo.completed %}warning{% else %}success{% endif %}">{% if todo.completed %}取消完成{% else %}标记完成{% endif %}</button></form><a href="{% url 'todo_update' todo.pk %}" class="btn btn-sm btn-info">编辑</a><a href="{% url 'todo_delete' todo.pk %}" class="btn btn-sm btn-danger">删除</a></div></div></div>{% endfor %}</div>{% else %}<p class="text-center">暂无待办事项</p>{% endif %}</div>
</div>
{% endblock %}
5.3 表单页面
<!-- templates/todos/todo_form.html -->
{% extends 'base.html' %}{% block title %}{{ title }}{% endblock %}{% block content %}
<div class="row"><div class="col-md-6 offset-md-3"><h2>{{ title }}</h2><form method="post">{% csrf_token %}{% for field in form %}<div class="mb-3">{{ field.label_tag }}{{ field }}{% if field.errors %}<div class="alert alert-danger">{{ field.errors }}</div>{% endif %}</div>{% endfor %}<button type="submit" class="btn btn-primary">保存</button><a href="{% url 'todo_list' %}" class="btn btn-secondary">返回</a></form></div>
</div>
{% endblock %}
六、流程图
七、扩展功能建议
- 添加任务分类功能
- 实现任务搜索和筛选
- 添加任务提醒功能
- 实现任务标签系统
- 添加任务导入导出功能
八、测试用例
# todos/tests.py
from django.test import TestCase, Client
from django.contrib.auth.models import User
from django.urls import reverse
from .models import Todoclass TodoTests(TestCase):def setUp(self):self.client = Client()self.user = User.objects.create_user(username='testuser',password='testpass123')self.client.login(username='testuser', password='testpass123')def test_todo_list_view(self):response = self.client.get(reverse('todo_list'))self.assertEqual(response.status_code, 200)def test_todo_create(self):data = {'title': '测试待办事项','description': '这是一个测试','priority': 'high'}response = self.client.post(reverse('todo_create'), data)self.assertEqual(response.status_code, 302)self.assertTrue(Todo.objects.filter(title='测试待办事项').exists())
九、总结
- 学习要点回顾:
- Django模型设计和实现
- CRUD视图的完整实现
- 表单处理和验证
- 模板系统的使用
- 用户认证和权限控制
怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!