Django入门教程:搭建你的第一个Python网站
开篇:一次从零到一的旅程
去年年底,公司需要做一个内部使用的项目管理工具,用于替代当时用Excel表格管理需求和任务的方式。作为一个技术负责人,我决定采用Django来搭建这个小系统——毕竟它以“开箱即用”著称,开发效率高,而且我们团队对Python也比较熟悉。这是我第一次完整使用Django做项目的后端,虽然不是什么复杂的项目,但在过程中确实踩了不少坑,也积累了一些经验。
今天我想分享这段经历,带你一步步用 Django 搭建一个属于自己的网站。我会结合真实场景,边讲边写代码,并且重点讲述我在实际工作中遇到的问题和解决方案。如果你是 Python 新手、或者刚准备接触 Web 开发,这篇文章应该能给你带来不少帮助。
问题描述:为什么选择 Django?
其实最开始,我也考虑过用 Flask 或者 FastAPI,因为它们更轻量级、灵活性更高。但仔细想想,Flask 太自由了,反而容易在初期投入大量时间去搭架子;而 FastAPI 虽然好,但我们项目里涉及大量的表单提交、后台管理界面这些功能,FastAPI 并不像 Django 那样天然支持这些。
更重要的是,我们的项目中用户权限、角色控制、日志记录等功能都是刚需。Django 内置的 Admin 管理后台简直就是为这种需求量身定做的。再加上 ORM 的强大和社区文档的丰富程度,我最终选择了 Django 来作为这次项目的技术栈。
不过说实话,虽然我对 Python 很熟,但真正上手用 Django 做全栈项目还是头一遭。从创建第一个 app 开始,我就遇到了一系列问题:
- 项目结构怎么组织?
- URL 怎么配置才合理?
- 数据库模型如何设计?
- 表单怎么处理?
- 前端模板怎么和后端对接?
- 如何部署上线?
别急,这些问题我都一个一个地解决了,下面我将带你从0到1搭建一个完整的项目。
解决方案:快速启动你的 Django 项目
我们先从最基础的部分讲起:安装 Django 并创建一个项目。
1. 安装 Django
推荐你使用虚拟环境(virtual environment)来管理依赖,这样可以避免不同项目之间的依赖冲突。
python -m venv venv
source venv/bin/activate # Windows 上使用 venv\Scripts\activate
pip install django
安装完成后,可以用如下命令验证是否安装成功:
django-admin --version
2. 创建项目
接着使用 django-admin 快速生成项目骨架:
django-admin startproject mysite
cd mysite
目录结构如下:
mysite/
├── manage.py
└── mysite/
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
我们可以先启动本地服务器看看效果:
python manage.py runserver
访问 http://127.0.0.1:8000,你会看到熟悉的 "The install worked successfully! Congratulations!" 页面,说明一切正常。
项目背景:我们需要什么样的网站?
回到我们最初的业务场景:我们要搭建一个项目管理系统,用于管理项目成员、任务分配、状态变更等功能。
简单来说,系统至少要满足以下功能:
- 用户登录认证(Django 自带认证系统)
- 创建项目 & 查看项目列表
- 添加任务、修改任务状态(未开始 / 进行中 / 已完成)
- 分配任务给团队成员
- 后台管理页面自动更新数据(Django Admin)
所以接下来,我们将围绕这个功能展开构建。
开启第一个 App —— tasks
Django 鼓励开发者将功能模块化,每个功能对应一个 app。我们创建一个叫 tasks 的 app 来管理所有与任务相关的内容:
python manage.py startapp tasks
然后在 settings.py 中注册这个 app:
INSTALLED_APPS = [
...
'tasks.apps.TasksConfig',
]
设计数据库模型
我们要设计两个核心模型:Project 和 Task。
打开 tasks/models.py,写入以下内容:
from django.db import models
from django.contrib.auth.models import User
class Project(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Task(models.Model):
STATUS_CHOICES = (
('P', 'Pending'),
('IP', 'In Progress'),
('C', 'Completed'),
)
title = models.CharField(max_length=100)
description = models.TextField(blank=True, null=True)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
assignee = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
status = models.CharField(max_length=2, choices=STATUS_CHOICES, default='P')
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
这里有几个关键点需要注意:
- 外键关系:任务归属项目(Project),同时分配给用户(User)。
- 默认值设置:通过
default参数设置初始状态为 Pending。 - 空值处理:描述字段允许为空,便于前端展示。
- on_delete 设置:当项目或用户被删除时,任务如何处理?这里设为
SET_NULL,表示保留任务但取消关联。
保存之后执行迁移命令:
python manage.py makemigrations
python manage.py migrate
实现视图与模板:让数据动起来
接下来我们实现一些基本的视图(views)和模板(templates),用来展示项目和任务数据。
首先,我们在 tasks/views.py 中编写首页视图:
from django.shortcuts import render
from .models import Project, Task
def home(request):
projects = Project.objects.all()
tasks = Task.objects.select_related('project', 'assignee').all()
context = {
'projects': projects,
'tasks': tasks
}
return render(request, 'tasks/home.html', context)
注意几点优化:

- 使用
select_related()提前加载外键对象,防止 N+1 查询问题。 - 把所有项目和任务数据传入模板进行渲染。
然后我们创建 HTML 模板。在项目根目录下新建 templates/tasks 文件夹,创建 home.html:
<!-- templates/tasks/home.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Project Manager</title>
</head>
<body>
<h1>Projects</h1>
<ul>
{% for project in projects %}
<li>{{ project.name }}</li>
{% endfor %}
</ul>
<h1>Tasks</h1>
<table border="1">
<tr><th>Title</th><th>Status</th><th>Assignee</th></tr>
{% for task in tasks %}
<tr>
<td>{{ task.title }}</td>
<td>{{ task.get_status_display }}</td>
<td>{{ task.assignee.username|default:"Unassigned" }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>

现在还需要在 settings.py 中配置模板路径:
TEMPLATES = [
{
...
'DIRS': [BASE_DIR / 'templates'],
...
},
]
接着,在主应用目录下的 urls.py 添加路由:
from django.urls import path
from tasks.views import home
urlpatterns = [
path('', home, name='home'),
]
重启服务之后访问 /,你应该能看到所有项目的名称和任务列表!
实现表单功能:添加项目和任务
Django 提供了强大的 Form 类型来简化表单处理流程。我们可以为添加项目和任务分别创建对应的 form。
在 tasks/forms.py 中添加:
from django import forms
from .models import Project, Task
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = ['name', 'description']
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = ['title', 'description', 'project', 'assignee', 'status']
然后在 views.py 添加新视图:
from .forms import ProjectForm, TaskForm
def add_project(request):
if request.method == 'POST':
form = ProjectForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
form = ProjectForm()
return render(request, 'tasks/add_form.html', {'form': form, 'title': 'Add Project'})
def add_task(request):
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
form = TaskForm()
return render(request, 'tasks/add_form.html', {'form': form, 'title': 'Add Task'})
再写一个通用的模板 add_form.html:
{% extends "base.html" %}
{% block content %}
<h1>{{ title }}</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
{% endblock %}
以及一个简单的 base.html 模板放在 templates 根目录:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<div class="container">
{% block content %}{% endblock %}
</div>
</body>
</html>
最后在 urls.py 中添加路径:
path('project/new/', views.add_project, name='add_project'),
path('task/new/', views.add_task, name='add_task'),
测试一下访问 /project/new/ 和 /task/new/,填写表单后跳转回主页,就能看到数据已经正确入库了!
踩过的几个坑与解决方案
在整个开发过程中,我确实踩了几个比较典型的坑,这里分享出来给大家避个雷。
✅ 1. 模板找不到怎么办?
刚开始的时候总提示 TemplateDoesNotExist 错误,检查模板路径发现没有配置 TEMPLATES.DIRS。记得一定要在 settings.py 中加上你的模板根目录路径,否则 Django 默认只会查找每个 app 下的 templates 目录。
✅ 2. 表单提交失败,页面没反应
这种情况通常是 CSRF token 缺失导致的。确保你在模板中加入 {% csrf_token %},并且使用 POST 请求发送数据。Django 对安全性要求很高,不加的话会直接拒绝请求。
✅ 3. 外键字段显示用户名而不是ID
Django 在展示 ForeignKey 字段时,默认会显示 ID,但这对用户很不友好。有两种办法解决:
- 使用
__str__方法返回可读名,比如我们在模型里写了return self.name; - 在模板中使用
{{ obj.field.related_name }},比如{{ task.assignee.username }}。
✅ 4. 迁移文件冲突或出错
有时候执行 makemigrations 会报错,尤其是在多人协作或版本切换频繁的情况下。可以尝试删除所有 migrations 文件(除了 __init__.py)和数据库中的 django_migrations 表,再重新运行迁移。当然这只能在开发阶段用,生产环境慎操作。
效果总结:我们的网站跑起来了!
经过上面这一系列步骤,我们已经成功用 Django 构建了一个具有基础 CRUD 功能的任务管理系统。它的优点包括:
- 开发速度快,借助 Admin 系统和 ORM,不需要自己写很多 SQL;
- 结构清晰,模块化程度高;
- 易于维护和扩展,未来加上权限管理、日历提醒、邮件通知等都不是问题;
- 生产可用性强,配合 Gunicorn + Nginx 可以上线。
对于我们内部使用的小工具来说,这套系统已经非常够用了。更重要的是,整个过程教会了我如何快速构建一个可靠的 Django 应用,并解决各种现实问题。
我的几个建议:新手入门 Django 的注意事项
作为一个走过弯路的人,想给正在学习 Django 的朋友几个建议:
- 别怕官方文档,它是最好的资源:Django 官方文档写得非常详细,而且更新频率高。有问题多查文档,比找 Stack Overflow 更准确。
- 善用 Django Admin 系统:这是 Django 最大的优势之一,不仅能快速实现数据管理,还能节省大量的开发工作。
- 学会使用调试器:在 VSCode 或 PyCharm 中启用断点调试是非常有必要的。有些逻辑错误光靠 print 是很难定位的。
- 提前规划 URL 结构:URL 是网站的入口,一开始设计不好后面改起来会很痛苦。建议采用 RESTful 风格。
- 性能也要考虑:虽然 Django 很快,但在并发较高的时候也可能出现瓶颈。可以考虑引入缓存机制(如 Redis)、异步任务队列(如 Celery)来优化。
- 部署时注意静态资源:Django 不擅长处理静态文件,建议用 Nginx 来托管 CSS/JS/images,Gunicorn 跑 Django 本身。
后记:Django 仍然是现代 Web 开发的利器
虽然现在前端框架层出不穷,Node.js、Go、Rust 也开始在 Web 后端崭露头角,但我始终认为,Django 依然是中小型项目中最实用的选择之一。它不仅降低了开发门槛,更重要的是能够让我们专注于业务逻辑本身,而不是陷入底层细节中。
如果你是一个刚刚踏入后端开发领域的新手,或者想要尝试用 Python 做一个完整的网站,Django 无疑是一条正确的入门之路。
希望我的这篇分享对你有所帮助。如果有什么问题,欢迎留言交流。咱们一起进步!

评论 0