每天40分玩转Django:实操 Todo List应用

实操 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 %}

六、流程图

在这里插入图片描述

七、扩展功能建议

  1. 添加任务分类功能
  2. 实现任务搜索和筛选
  3. 添加任务提醒功能
  4. 实现任务标签系统
  5. 添加任务导入导出功能

八、测试用例

# 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())

九、总结

  1. 学习要点回顾:
    • Django模型设计和实现
    • CRUD视图的完整实现
    • 表单处理和验证
    • 模板系统的使用
    • 用户认证和权限控制

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/490831.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Freertos任务切换

一、操作系统进行任务切换的时机&#xff1a; 采用信号量实现任务的互斥&#xff1a; 二、FreeRTOS 任务切换场合 PendSV 中断的时候提到了上下文(任务)切换被触发的场合&#xff1a; ● 可以执行一个系统调用 ● 系统滴答定时器(SysTick)中断。 1、执行系统调用 执行系统…

【Linux】自定义项目-进度条

更多精彩内容..... &#x1f389;❤️播主の主页✨&#x1f618; Stark、-CSDN博客 准备工作&#xff1a;"\r"与"\n"字符 ①&#xff1a;基本含义 在C语言和Linux环境中&#xff0c;\r是回车符&#xff0c;\n是换行符&#xff0c;用于控制文本格式和输出…

【ubuntu24.04】PDFMathTranslate 本地PDF翻译GPU部署

https://huggingface.co/spaces/reycn/PDFMathTranslate-Docker排不上号官方都是要安装包,感觉可以本地试着源码部署一下, http://localhost:7860/官方是这个端口,但是我本地启动是:5000IDEA 里本地 backend启动效果 GUI 是监听7860的

基于卷积神经网络的垃圾分类系统实现(GUI应用)

1.摘要 本文主要实现了一个卷积神经网络模型进行垃圾图像分类&#xff0c;为了提高垃圾分类模型的准确率&#xff0c;使用使用Batch Normalization层、使用早期停止策略来防止过拟合等方法来优化模型&#xff0c;实验结果显示最终优化后的模型准确率较高90%左右。最终&#xf…

Vulnstack红日安全内网域渗透靶场2实战攻略

一&#xff1a;环境搭建 新增的网卡VMnet2&#xff0c;ip调成10段。 PC配置如下&#xff1a; DC在该环境中充当是域控。DC配置如下 &#xff1a; WEB配置&#xff1a;需要两块网卡&#xff0c;相当于网关服务器。 作者把外网网段都写成了192.168.111.1/24&#xff0c;我们可以…

Http协议在网站中的体现

文章目录 1. Http协议简介2. 网站中的体现2.1 访问网站2.2 请求2.3 请求头2.4 请求方式2.5 响应 3. 总结 1. Http协议简介 HTTP&#xff08;超文本传输协议&#xff09; 是一种广泛应用于互联网上的应用层协议&#xff0c;用于在Web浏览器和Web服务器之间传输数据。HTTP协议定…

JavaWeb——前端三剑客

前言&#xff1a;今天开始学习JavaWeb相关内容了&#xff0c;陆续会总结一些前后端分离开发的相关知识&#xff0c;有遗漏和错误的地方欢迎大家指出~ 目录 一、前端三剑客二、HTML2.1 HTML介绍2.2 常用标签 三、 CSS3.1 CSS介绍3.2 CSS引用的三种形式3.3. CSS选择器及其类型3.…

【经典】制造供应链四类策略(MTS、MTO、ATO、ETO)细说

关注作者 制造供应链的牛鞭问题与复杂问题主要是从两个方面解决&#xff0c;一是同步化供应链消减从需求到供应的放大效应&#xff0c;二是供应链细分&#xff0c;针对不同的客户、不同的需求供应的匹配策略来应对复杂性&#xff0c;更好的满足客户并以最低的总成本来实现。 对…

fixture装饰器

普通代码案例&#xff1a; python本身执行 import pytestdef init_new():print("init_new...")return Truedef test_case(init_new):if init_new is True:print("如果init_new返回True&#xff0c;就执行用例test_case")if __name__ __main__:#用python本…

数智读书笔记系列008 智人之上:从石器时代到AI时代的信息网络简史

书名:智人之上&#xff1a;从石器时代到AI时代的信息网络简史 作者:&#xff3b;以&#xff3d;尤瓦尔赫拉利 译者:林俊宏 出版时间:2024-09-01 ISBN:9787521768527 中信出版集团制作发行 作者信息 尤瓦尔・赫拉利 1976 年出生于以色列海法&#xff0c;是牛津大学历史学…

【C++】10___文件操作

目录 一、文本文件---写文件 二、文本文件---读文件 三、二进制文件---写文件 四、二进制文件---读文件 一、文本文件---写文件 通过文件操作可以将数据持久化 对文件操作需要包含头文件<fstream> 文件类型分两类&#xff1a; 文本文件&#xff1a;文件以文本的ASCII码形…

信号处理:概念、技术、领域

目录 基本概念 主要技术 应用领域 信号处理是一个涉及分析、修改和再生信号的多学科领域。信号可以是各种形式的&#xff0c;例如声音、图像、视频或其他类型的监测数据。信号处理的主要目标是提取有用的信息并增强信号的质量。以下是信号处理的一些基本概念和应用&#xff…

排序算法(5):归并排序

问题 排序 [30, 24, 5, 58, 18, 36, 12, 42, 39] 归并排序 归并排序采用分治法&#xff0c;将序列分成若干子序列&#xff0c;每个子序列有序后再合并成有序的完整序列。 在数组排序中&#xff0c;如果只有一个数&#xff0c;那么它本身就是有序的。如果有两个数&#xff0…

vue 自定义组件image 和 input

本章主要是介绍自定义的组件&#xff1a;WInput&#xff1a;这是一个验证码输入框&#xff0c;自动校验&#xff0c;输入完成回调等&#xff1b;WImage&#xff1a;这是一个图片展示组件&#xff0c;集成了缩放&#xff0c;移动等操作。 目录 一、安装 二、引入组件 三、使用…

基于Java的图书借阅管理系统详细设计和实现

目录 一、前言介绍&#xff1a; 二、主要技术&#xff1a; 2.1 Java技术介绍&#xff1a; 2.2 MYSQL数据库&#xff1a; 三、系统设计&#xff1a; 3.1 系统架构设计&#xff1a; 3.2 登录时序图设计&#xff1a; 四、功能截图&#xff1a; 4.1 用户登录注册 4.2 系统…

每天五分钟深度学习:解析m个样本向量化前向传播的原理

本文重点 上一节课程中,我们学会了多样本的前向传播的向量化形式,使用这种方式我们可以同时计算m个样本的前向传播,我们将m个样本以矩阵形式表示,实现了m个样本的向量化,本节课程我们再来看一下为什么使用上节课程的方式就可以完成m个样本的向量化。 x(1)、x(2)、x(3)在…

Android显示系统(10)- SurfaceFlinger内部结构

Android显示系统(01)- 架构分析 Android显示系统(02)- OpenGL ES - 概述 Android显示系统(03)- OpenGL ES - GLSurfaceView的使用 Android显示系统(04)- OpenGL ES - Shader绘制三角形 Android显示系统(05)- OpenGL ES - Shader绘制三角形(使用glsl文件) Android显…

软考高级架构 - 11.1- 信息物理系统CPS

信息物理系统CPS 信息物理系统(CPS)是控制系统、嵌入式系统的扩展与延伸。通过集成先进的感知、计算、通信、控制等信息技术和自动控制技&#xff0c;构建了物理空间与信息空间中人、机、物、环境、信息等要素相互映射、适时交互、高效协同的夏杂系统。 CPS的本质是基于…

数据可视化的Python实现

一、GDELT介绍 GDELT ( www.gdeltproject.org ) 每时每刻监控着每个国家的几乎每个角落的 100 多种语言的新闻媒体 -- 印刷的、广播的和web 形式的&#xff0c;识别人员、位置、组织、数量、主题、数据源、情绪、报价、图片和每秒都在推动全球社会的事件&#xff0c;GDELT 为全…

【GIS教程】使用GDAL-Python将tif转为COG并在ArcGIS Js前端加载-附完整代码

目录 一、数据格式 二、COG特点 三、使用GDAL生成COG格式的数据 四、使用ArcGIS Maps SDK for JavaScript加载COG格式数据 一、数据格式 COG&#xff08;Cloud optimized GeoTIFF&#xff09;是一种GeoTiff格式的数据。托管在 HTTP 文件服务器上&#xff0c;可以代替geose…