Django个人主页开发实战:从0到1构建动态网站
作为一名开发者,我最近完成了一个基于Django的个人主页项目,在这个过程中系统学习了Django框架的核心功能。本文将详细分享完整的开发过程,包含所有代码实现和运行结果,希望能帮助正在学习Django的朋友们。
一、项目初始化与环境配置
1. 安装Django
# 安装最新版本的Django
pip install django
# 验证安装
python -m django --version
2. 创建项目
# 创建项目目录
django-admin startproject personal_website
# 进入项目目录
cd personal_website
3. 创建应用
# 创建portfolio应用
python manage.py startapp portfolio
4. 配置应用 在personal_website/settings.py中添加应用:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'portfolio', # 添加portfolio应用
]
5. 配置媒体文件
# 媒体文件配置
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'
二、数据模型设计与实现
1. 定义核心模型 在portfolio/models.py中定义数据模型:
from django.db import models
class PersonalInfo(models.Model):
"""个人信息模型"""
name = models.CharField(max_length=100, verbose_name='姓名')
title = models.CharField(max_length=200, verbose_name='职位')
bio = models.TextField(verbose_name='个人简介')
email = models.EmailField(verbose_name='邮箱')
phone = models.CharField(max_length=20, verbose_name='电话')
wechat = models.CharField(max_length=50, verbose_name='微信')
avatar = models.ImageField(upload_to='avatars/', blank=True, null=True, verbose_name='头像')
class Meta:
verbose_name = '个人信息'
verbose_name_plural = '个人信息'
def __str__(self):
return self.name
class ResearchDirection(models.Model):
"""研究方向模型"""
name = models.CharField(max_length=100, verbose_name='研究方向')
class Meta:
verbose_name = '研究方向'
verbose_name_plural = '研究方向'
def __str__(self):
return self.name
class Course(models.Model):
"""课程模型"""
title = models.CharField(max_length=200, verbose_name='课程名称')
description = models.TextField(verbose_name='课程描述')
is_current = models.BooleanField(default=True, verbose_name='当前课程')
class Meta:
verbose_name = '课程'
verbose_name_plural = '课程'
def __str__(self):
return self.title
class Project(models.Model):
"""项目模型"""
title = models.CharField(max_length=200, verbose_name='项目名称')
description = models.TextField(verbose_name='项目描述')
link = models.URLField(blank=True, null=True, verbose_name='项目链接')
class Meta:
verbose_name = '项目'
verbose_name_plural = '项目'
def __str__(self):
return self.title
class BlogPost(models.Model):
"""博客文章模型"""
title = models.CharField(max_length=200, verbose_name='标题')
content = models.TextField(verbose_name='内容')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
class Meta:
verbose_name = '博客文章'
verbose_name_plural = '博客文章'
def __str__(self):
return self.title
2. 数据库迁移
# 创建迁移文件
python manage.py makemigrations
# 执行迁移
python manage.py migrate
3. 创建超级用户
# 创建超级用户(用于后台管理)
python manage.py createsuperuser
三、视图函数与URL配置
1. 编写视图函数 在portfolio/views.py中实现视图:
from django.shortcuts import render
from .models import PersonalInfo, ResearchDirection, Course, Project, BlogPost
def home(request):
"""首页视图"""
personal_info = PersonalInfo.objects.first()
research_directions = ResearchDirection.objects.all()
courses = Course.objects.all()
projects = Project.objects.all()
context = {
'personal_info': personal_info,
'research_directions': research_directions,
'courses': courses,
'projects': projects
}
return render(request, 'portfolio/home.html', context)
def blog(request):
"""博客页面视图"""
blog_posts = BlogPost.objects.order_by('-created_at')
context = {
'blog_posts': blog_posts
}
return render(request, 'portfolio/blog.html', context)
2. 配置URL 在portfolio/urls.py中配置应用URL:
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('blog/', views.blog, name='blog'),
]
在personal_website/urls.py中包含应用URL:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('portfolio.urls')),
]
# 添加媒体文件支持
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
四、模板系统与前端实现
1. 创建模板目录
# 创建模板目录结构
mkdir -p portfolio/templates/portfolio
2. 编写首页模板 创建portfolio/templates/portfolio/home.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>个人主页</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 40px 0;
text-align: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.header-content {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.avatar {
width: 150px;
height: 150px;
border-radius: 50%;
background-color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 60px;
margin-bottom: 20px;
}
.personal-info {
text-align: center;
}
.personal-info h1 {
font-size: 36px;
margin-bottom: 10px;
}
.personal-info p {
font-size: 18px;
margin-bottom: 20px;
}
.contact-info {
display: flex;
justify-content: center;
gap: 30px;
margin-top: 20px;
}
.contact-item {
display: flex;
align-items: center;
gap: 5px;
}
nav {
background-color: white;
padding: 20px 0;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
margin-bottom: 30px;
}
.nav-links {
display: flex;
justify-content: center;
gap: 40px;
}
.nav-links a {
color: #333;
text-decoration: none;
font-size: 16px;
font-weight: 500;
transition: color 0.3s;
}
.nav-links a:hover {
color: #667eea;
}
.section {
background-color: white;
padding: 30px;
margin-bottom: 30px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.section h2 {
color: #667eea;
margin-bottom: 20px;
font-size: 24px;
border-bottom: 2px solid #667eea;
padding-bottom: 10px;
}
.bio {
font-size: 16px;
line-height: 1.8;
}
.research-directions {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-top: 20px;
}
.direction-tag {
background-color: #f0f0f0;
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
}
.courses {
margin-top: 20px;
}
.course-item {
background-color: #f9f9f9;
padding: 15px;
border-radius: 8px;
margin-bottom: 15px;
}
.course-item h3 {
color: #667eea;
margin-bottom: 10px;
}
.projects {
margin-top: 20px;
}
.project-item {
background-color: #f9f9f9;
padding: 15px;
border-radius: 8px;
margin-bottom: 15px;
}
.project-item h3 {
color: #667eea;
margin-bottom: 10px;
}
.project-link {
color: #667eea;
text-decoration: none;
font-weight: 500;
}
.project-link:hover {
text-decoration: underline;
}
footer {
background-color: #333;
color: white;
text-align: center;
padding: 20px 0;
margin-top: 50px;
}
</style>
</head>
<body>
<header>
<div class="container header-content">
<div class="avatar">
{% if personal_info.avatar %}
<img src="{{ personal_info.avatar.url }}" alt="{{ personal_info.name }}" style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;">
{% else %}
👤
{% endif %}
</div>
<div class="personal-info">
<h1>{{ personal_info.name }}</h1>
<p>{{ personal_info.title }}</p>
<div class="contact-info">
<div class="contact-item">
📧 {{ personal_info.email }}
</div>
<div class="contact-item">
📱 {{ personal_info.phone }}
</div>
<div class="contact-item">
💬 {{ personal_info.wechat }}
</div>
</div>
</div>
</div>
</header>
<nav>
<div class="container">
<div class="nav-links">
<a href="{% url 'home' %}">首页</a>
<a href="{% url 'blog' %}">博客</a>
</div>
</div>
</nav>
<div class="container">
<section class="section">
<h2>个人简介</h2>
<div class="bio">
{{ personal_info.bio|linebreaks }}
</div>
</section>
<section class="section">
<h2>研究方向</h2>
<div class="research-directions">
{% for direction in research_directions %}
<div class="direction-tag">
{{ direction.name }}
</div>
{% endfor %}
</div>
</section>
<section class="section">
<h2>当前课程</h2>
<div class="courses">
{% for course in courses %}
<div class="course-item">
<h3>{{ course.title }}</h3>
<p>{{ course.description }}</p>
</div>
{% endfor %}
</div>
</section>
<section class="section">
<h2>项目</h2>
<div class="projects">
{% for project in projects %}
<div class="project-item">
<h3>{{ project.title }}</h3>
<p>{{ project.description }}</p>
{% if project.link %}
<a href="{{ project.link }}" class="project-link" target="_blank">查看项目</a>
{% endif %}
</div>
{% endfor %}
</div>
</section>
</div>
<footer>
<div class="container">
<p>© {{ personal_info.name }} - 个人主页</p>
</div>
</footer>
</body>
</html>
3. 编写博客页面模板 创建portfolio/templates/portfolio/blog.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 40px 0;
text-align: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.header-content h1 {
font-size: 36px;
}
nav {
background-color: white;
padding: 20px 0;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
margin-bottom: 30px;
}
.nav-links {
display: flex;
justify-content: center;
gap: 40px;
}
.nav-links a {
color: #333;
text-decoration: none;
font-size: 16px;
font-weight: 500;
transition: color 0.3s;
}
.nav-links a:hover {
color: #667eea;
}
.section {
background-color: white;
padding: 30px;
margin-bottom: 30px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.section h2 {
color: #667eea;
margin-bottom: 20px;
font-size: 24px;
border-bottom: 2px solid #667eea;
padding-bottom: 10px;
}
.blog-posts {
margin-top: 20px;
}
.blog-post {
background-color: #f9f9f9;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
transition: transform 0.3s, box-shadow 0.3s;
}
.blog-post:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.blog-post h3 {
color: #667eea;
margin-bottom: 10px;
font-size: 20px;
}
.blog-post .date {
color: #999;
font-size: 14px;
margin-bottom: 15px;
}
.blog-post .content {
font-size: 16px;
line-height: 1.8;
}
footer {
background-color: #333;
color: white;
text-align: center;
padding: 20px 0;
margin-top: 50px;
}
</style>
</head>
<body>
<header>
<div class="container header-content">
<h1>博客</h1>
</div>
</header>
<nav>
<div class="container">
<div class="nav-links">
<a href="{% url 'home' %}">首页</a>
<a href="{% url 'blog' %}">博客</a>
</div>
</div>
</nav>
<div class="container">
<section class="section">
<h2>博客文章</h2>
<div class="blog-posts">
{% for post in blog_posts %}
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div class="date">发布于: {{ post.created_at|date:"Y-m-d H:i" }}</div>
<div class="content">
{{ post.content|linebreaks }}
</div>
</div>
{% empty %}
<p>暂无博客文章</p>
{% endfor %}
</div>
</section>
</div>
<footer>
<div class="container">
<p>© 博客页面</p>
</div>
</footer>
</body>
</html>
五、后台管理配置
1. 注册模型到后台 在portfolio/admin.py中注册模型:
from django.contrib import admin
from .models import PersonalInfo, ResearchDirection, Course, Project, BlogPost
admin.site.register(PersonalInfo)
admin.site.register(ResearchDirection)
admin.site.register(Course)
admin.site.register(Project)
admin.site.register(BlogPost)
六、运行项目
1. 启动开发服务器
# 启动开发服务器
python manage.py runserver
2. 访问项目
- 个人主页:http://127.0.0.1:8000/
- 后台管理:http://127.0.0.1:8000/admin/
- 用户名:admin
- 密码:admin123
七、运行成功的图片位置
个人主页截图 
八、项目优化与扩展
1. 性能优化
- 使用select_related和prefetch_related减少数据库查询
- 配置缓存系统
- 优化静态文件加载
2. 功能扩展
- 添加用户认证系统
- 实现评论功能
- 添加搜索功能
- 集成第三方服务(如社交媒体分享)
3. 部署建议
- 使用Gunicorn或uWSGI作为WSGI服务器
- 配置Nginx作为反向代理
- 使用PostgreSQL或MySQL作为生产数据库
- 配置HTTPS
九、总结
通过这个个人主页项目,我系统地学习了Django的核心功能,包括:
- 项目结构和配置管理
- 数据模型设计与数据库操作
- 视图函数和URL路由
- 模板系统和前端渲染
- 后台管理系统
- 媒体文件处理
Django的"batteries included"理念让我能够快速构建功能完整的Web应用,而不需要从零开始实现所有组件。同时,Django的文档和社区支持也让学习过程变得更加顺畅。
这个项目不仅是一个展示个人信息的平台,也是我学习Django的实践成果。通过不断完善和扩展这个项目,我可以进一步提升自己的Web开发能力。
希望本文的详细代码和实现过程能够对正在学习Django的朋友们有所帮助。如果有任何问题或建议,欢迎在评论区留言交流!
项目地址: https://gitcode.com/gcw_NAormESZ/DJango_personal_web.git
技术栈:
- Python 3.14
- Django 6.0.3
- HTML5/CSS3
- SQLite(开发环境)
功能特性:
- 动态个人主页
- 博客系统
- 后台管理
- 响应式设计
- 媒体文件支持
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)