从 0 到 1:Django 动态个人主页实战(附踩坑记录)
一、项目背景
作为数据科学与大数据专业的学生,在学习 Python Django 框架开发实践课程时,我完成了一个动态个人主页项目。这个项目不仅满足了「至少两个页面、后台可修改、非静态页面」的作业要求,还完整实践了 Django MVT 架构,非常适合作为 Django 入门练手项目。
最终效果:个人主页(左侧个人信息+右侧内容展示)+ 详细信息页,支持页面跳转,数据动态渲染。
二、项目核心功能
三、前期准备(环境搭建)
新手先做好环境准备,避免后续报错,步骤很简单,跟着来就行:
1. 环境配置
安装Django命令(CMD中执行):
pip install django==5.2
2. 项目初始化
打开CMD,进入想要存放项目的文件夹(比如D:\myself),依次执行以下命令,创建项目和应用:
# 1. 创建Django项目(项目名mysite,可自定义) django-admin startproject mysite # 2. 进入项目目录 cd mysite # 3. 创建应用(应用名polls,可自定义) python manage.py startapp polls # 4. 启动测试服务(验证项目是否创建成功) python manage.py runserver
启动后访问 http://127.0.0.1:8000/,看到Django默认页面,说明项目初始化成功。
四、完整开发步骤(核心部分)
Django 采用经典的 MVT(Model-View-Template)架构,我在项目中严格遵循了这一设计:
- ✅ 双页面交互:个人主页(展示基础信息)+ 详细信息页(展示完整联系方式、研究方向)
- ✅ 后台数据管理:通过 Django Admin 后台修改个人信息,前端页面自动同步更新
- ✅ 动态渲染:所有数据从数据库读取,而非写死在 HTML 中,完全符合「非静态页面」要求
- ✅ 响应式布局:页面样式适配 PC 端,视觉清晰美观
最终效果:个人主页(左侧个人信息+右侧内容展示)+ 详细信息页,支持页面跳转,数据动态渲染。
-
Python版本:3.9+(避免版本过高导致依赖不兼容)
-
Django版本:5.2(稳定版,适合新手)
-
其他依赖:无需额外安装,Django自带核心功能
1. Model(模型层)
定义 Student 模型,存储个人信息:
from django.db import models
class Student(models.Model):
name = models.CharField(max_length=20, verbose_name="姓名")
avatar = models.ImageField(upload_to="avatars/", blank=True, verbose_name="头像")
bio = models.TextField(verbose_name="个人简介")
research = models.TextField(verbose_name="研究方向")
current_course = models.CharField(max_length=50, verbose_name="当前课程")
email = models.EmailField(verbose_name="邮箱")
phone = models.CharField(max_length=11, verbose_name="手机")
def __str__(self):
return self.name
- 作用:将 Python 对象映射为数据库表,无需编写 SQL 即可操作数据
- 注册到 Admin 后台后,可直接在浏览器中增删改查个人信息
代码说明:定义了6个字段,对应个人主页需要展示的所有信息,Meta类用于设置后台显示的中文名称,新手可直接复制,无需修改。
模型定义完成后,执行数据库迁移命令(CMD中,项目根目录):

1.1 数据库迁移 + 创建管理员
# 生成迁移文件 python manage.py makemigrations # 执行迁移建表 python manage.py migrate # 创建超级管理员(按提示输用户名、邮箱、密码) python manage.py createsuperuser1.2 admin.py 后台注册代码(polls 文件夹下)
from django.contrib import admin from .models import Student admin.site.register(Student)1.3核心:路由修复(解决所有 URL 404 报错)
1.3.1 新建 polls/urls.py

from django.urls import path from . import views app_name = "polls" urlpatterns = [ path("", views.profile_home, name="profile_home"), path("detail/", views.profile_detail, name="profile_detail"), ]1.3.2 修改 mysite/urls.py(根路由),全选替换成这段

from django.contrib import admin from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), # 主页直接访问127.0.0.1:8000,不用加polls前缀,解决404 path("", include("polls.urls")), ]1.4、views.py 视图代码(polls 文件夹下)

from django.shortcuts import render, get_object_or_404 from .models import Student # 个人主页 def profile_home(request): student = get_object_or_404(Student, name="陈心怡") return render(request, "polls/profile_home.html", {"student": student}) # 详情页 def profile_detail(request): student = get_object_or_404(Student, name="陈心怡") return render(request, "polls/profile_detail.html", {"student": student})1.5模板文件夹路径(必须严格建)
polls → templates → polls(两层,少一层就报错)
2. View(视图层)
编写视图函数处理请求,从数据库查询数据并传递给模板:
from django.shortcuts import render, get_object_or_404
from .models import Student
def profile_home(request):
# 查询姓名为「陈心怡」的学生记录
student = get_object_or_404(Student, name="陈心怡")
return render(request, "polls/profile_home.html", {"student": student})
def profile_detail(request):
student = get_object_or_404(Student, name="陈心怡")
return render(request, "polls/profile_detail.html", {"student": student})
- 作用:接收 HTTP 请求,执行业务逻辑(查询数据库),准备渲染页面所需数据
get_object_or_404:查询不到数据时自动返回 404 页面,提升用户体验
3. Template(模板层)
Template(模板层)—— 页面渲染(粉色Hello Kitty风格)
模板层负责将视图传递的数据渲染成HTML页面,也是页面样式的核心,新手注意「模板路径必须正确」,否则会报「TemplateDoesNotExist」错误。
3.1 创建模板文件夹(关键步骤)
在 polls 文件夹下,依次创建以下文件夹结构(严格按照这个路径,不能错)polls/
└── templates/
└── polls/
├── profile_home.html # 个人主页模板
└── profile_detail.html # 详细信息页模板
⚠️ 新手坑:模板文件夹必须是「templates/polls/」,少一层、多一层都会导致模板找不到。
3.2 个人主页模板(profile_home.html)
粉色Hello Kitty风格,包含导航栏、左侧个人信息、右侧内容展示(关于我、技能树、项目展示),直接复制粘贴到 profile_home.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ student.name }} - 个人主页</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Microsoft Yahei", sans-serif;
}
body {
background: #fff0f5;
color: #333;
}
/* 顶部导航 */
.navbar {
background: #fff;
padding: 15px 20px;
border-bottom: 1px solid #ffd6e0;
display: flex;
justify-content: center;
gap: 30px;
}
.navbar a {
text-decoration: none;
color: #b86b97;
font-weight: 500;
padding: 5px 10px;
}
.navbar a:hover {
color: #ff69b4;
}
/* 容器布局 */
.container {
max-width: 1200px;
margin: 20px auto;
display: grid;
grid-template-columns: 320px 1fr;
gap: 20px;
padding: 0 20px;
}
/* 卡片样式 */
.card {
background: #fff;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 8px rgba(255, 105, 180, 0.1);
margin-bottom: 15px;
}
/* 左侧个人信息 */
.profile-card {
text-align: center;
}
.avatar {
width: 100px;
height: 100px;
border-radius: 50%;
background: #ffe4e1;
margin: 0 auto 15px;
overflow: hidden;
}
.avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.name {
font-size: 24px;
color: #b86b97;
margin-bottom: 8px;
}
.school {
font-size: 14px;
color: #999;
margin-bottom: 15px;
}
.contact {
font-size: 13px;
color: #666;
margin: 5px 0;
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
}
/* 右侧内容区 */
.section-title {
font-size: 18px;
color: #b86b97;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.section-content {
font-size: 14px;
line-height: 1.7;
color: #555;
}
.project-item {
background: #fff5f8;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
}
.project-title {
color: #c83c7a;
font-weight: 500;
margin-bottom: 8px;
}
.project-desc {
font-size: 13px;
color: #666;
margin-bottom: 10px;
}
.project-tech {
font-size: 12px;
color: #999;
margin-bottom: 10px;
}
.btn {
display: inline-block;
padding: 6px 15px;
background: #e6679d;
color: #fff;
border-radius: 20px;
text-decoration: none;
font-size: 13px;
}
.tag {
display: inline-block;
padding: 4px 10px;
background: #ffe4e1;
color: #c83c7a;
border-radius: 15px;
font-size: 12px;
margin-right: 8px;
margin-bottom: 8px;
}
/* 底部版权 */
.footer {
text-align: center;
padding: 15px;
color: #b86b97;
font-size: 12px;
margin-top: 30px;
}
</style>
</head>
<body>
<div class="navbar">
<a href="{% url 'polls:profile_home' %}">🏠 首页</a>
<a href="#">📂 项目展示</a>
<a href="/admin/">⚙️ 后台管理</a>
</div>
<div class="container">
<!-- 左侧个人信息 -->
<div>
<div class="card profile-card">
<div class="avatar">
<!-- 替换成你的Hello Kitty头像 -->
<img src="https://static.vecteezy.com/system/resources/previews/011/078/421/original/cute-kitty-cat-cartoon-doodle-illustration-vector.jpg" alt="头像">
</div>
<h1 class="name">{{ student.name }}</h1>
<p class="school">数据科学与大数据技术 · 2023级</p>
<p class="school">上海杉达学院</p>
<p class="contact">📧 {{ student.email }}</p>
<p class="contact">📱 {{ student.phone }}</p>
</div>
</div>
<!-- 右侧内容区 -->
<div>
<!-- 关于我 -->
<div class="card">
<h2 class="section-title">💡 关于我</h2>
<p class="section-content">{{ student.bio }}</p>
</div>
<!-- 兴趣方向 -->
<div class="card">
<h2 class="section-title">❤️ 兴趣方向</h2>
<div>
<span class="tag">数据分析与可视化</span>
<span class="tag">Django框架开发实践</span>
<span class="tag">Web全栈开发</span>
</div>
</div>
<!-- 技能树 -->
<div class="card">
<h2 class="section-title">📊 技能树</h2>
<p class="section-content">编程语言:Python</p>
<p class="section-content">编程语言:JavaScript</p>
<p class="section-content">Web框架:Django</p>
<p class="section-content">数据库:SQL</p>
</div>
<!-- 最新项目 -->
<div class="card">
<h2 class="section-title">📁 最新项目</h2>
<div class="project-item">
<h3 class="project-title">Django 投票应用</h3>
<p class="project-desc">完成官方教程,实现完整的投票系统,支持问题发布、选项投票、结果展示</p>
<p class="project-tech">技术栈:Django 5.2, SQLite, Bootstrap</p>
<a href="#" class="btn">查看项目 →</a>
</div>
</div>
<!-- 学习动态 -->
<div class="card">
<h2 class="section-title">📝 学习动态</h2>
<p class="section-content" style="margin-bottom:10px;">完成了 Django 入门教程的第八部分,集成了测试工具栏 <br><small style="color:#999;">2026-03-22 14:36</small></p>
<p class="section-content">正在学习 Django 通用视图,感觉比函数视图简洁很多!<br><small style="color:#999;">2026-03-22 14:36</small></p>
</div>
</div>
</div>
<div class="footer">
© {{ student.name }} 的个人主页 | 上海杉达学院 数据科学与大数据技术 2023级
</div>
</body>
</html>
3. 详细信息页模板(profile_detail.html)
与主页风格统一,展示完整的个人信息,支持返回主页,复制粘贴到 profile_detail.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ student.name }} - 详细信息</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Microsoft Yahei", sans-serif;
}
body {
background: #fff0f5;
color: #333;
}
.navbar {
background: #fff;
padding: 15px 20px;
border-bottom: 1px solid #ffd6e0;
display: flex;
justify-content: center;
gap: 30px;
}
.navbar a {
text-decoration: none;
color: #b86b97;
font-weight: 500;
padding: 5px 10px;
}
.container {
max-width: 900px;
margin: 20px auto;
padding: 0 20px;
}
.card {
background: #fff;
border-radius: 12px;
padding: 25px;
box-shadow: 0 2px 8px rgba(255, 105, 180, 0.1);
}
h2 {
color: #b86b97;
margin-bottom: 20px;
}
.section {
margin-bottom: 25px;
}
.section h3 {
font-size: 16px;
color: #c83c7a;
margin-bottom: 12px;
}
.section p {
line-height: 1.7;
font-size: 14px;
color: #555;
}
.btn {
display: inline-block;
padding: 10px 20px;
background: #e6679d;
color: #fff;
text-decoration: none;
border-radius: 20px;
}
</style>
</head>
<body>
<div class="navbar">
<a href="{% url 'polls:profile_home' %}">🏠 首页</a>
<a href="#">📂 项目展示</a>
<a href="/admin/">⚙️ 后台管理</a>
</div>
<div class="container">
<div class="card">
<h2>{{ student.name }} 的详细信息</h2>
<div class="section">
<h3>个人简介</h3>
<p>{{ student.bio }}</p>
</div>
<div class="section">
<h3>研究方向</h3>
<p>{{ student.research }}</p>
</div>
<div class="section">
<h3>当前课程</h3>
<p>{{ student.current_course }}</p>
</div>
<div class="section">
<h3>联系方式</h3>
<p>邮箱:{{ student.email }}</p>
<p>手机:{{ student.phone }}</p>
</div>
<a href="{% url 'polls:profile_home' %}" class="btn">← 返回主页</a>
</div>
</div>
</body>
</html>
4. URL(路由层)
配置 URL 路由,将请求映射到对应的视图函数:
# polls/urls.py
from django.urls import path
from . import views
app_name = "polls"
urlpatterns = [
path("profile/", views.profile_home, name="profile_home"),
path("profile/detail/", views.profile_detail, name="profile_detail"),
]
# mysite/urls.py(根路由)
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("polls/", include("polls.urls")),
]
- 作用:建立 URL 与视图函数的映射关系,决定用户访问某个地址时执行哪段代码
四、启动服务器并添加数据
运行 runserver 启动开发服务器,访问后台地址登录管理员账号。依次添加学生信息、兴趣方向、技能、课程、项目、学习动态等内容。所有内容添加后即可在后台管理界面进行增删改查操作。


五、项目运行与踩坑记录
1. 关键步骤
- 创建模板文件夹:
polls/templates/polls/,存放profile_home.html和profile_detail.html - 数据库迁移:
python manage.py makemigrations python manage.py migrate - 创建超级管理员:
python manage.py createsuperuser - 启动服务:
python manage.py runserver - 访问地址:
- 个人主页:
http://127.0.0.1:8000/polls/profile/ - 详细信息页:
http://127.0.0.1:8000/polls/profile/detail - 后台管理:
http://127.0.0.1:8000/admin/
- 个人主页:
2. 踩坑与解决
坑 1:TemplateDoesNotExist 模板不存在
- 原因:模板文件路径错误,或文件名后缀为
.txt(Windows 隐藏后缀导致) - 解决:
- 确保路径为
polls/templates/polls/xxx.html - 打开文件夹「查看」→ 勾选「文件扩展名」,将
.html.txt改为.html - 或使用 CMD 命令改名:
ren profile_home.html.txt profile_home.html
- 确保路径为
坑 2:No Student matches the given query 数据库查询失败
- 原因:数据库中没有姓名为「陈心怡」的
Student记录 - 解决:登录 Admin 后台,手动添加一条学生记录,或在视图中使用
get_or_create自动创建
坑 3:IndentationError 缩进错误
- 原因:Python 对缩进严格,路由代码缩进不一致
- 解决:确保所有路由代码与
urlpatterns = [保持同一级缩进,使用 4 个空格或 1 个 Tab,不要混用
五、项目总结
这个动态个人主页项目,完整覆盖了 Django 开发的核心流程:
- 从模型定义、视图编写、模板渲染到路由配置,实践了 MVT 架构
- 通过 Admin 后台管理数据,实现了「后台修改、前端自动更新」的动态效果
- 解决了模板路径、数据库查询、缩进等常见问题,加深了对 Django 框架的理解
如果你也在学习 Django,这个项目非常适合作为入门练手案例,代码简洁、功能完整,还能直接作为课程作业提交~
💡 后续可扩展方向:
- 增加头像上传功能
- 优化移动端响应式布局
- 添加访客统计功能
- 接入 Markdown 编辑器编写个人简介
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)