blog/admin.py
从零开始,搭建我的第一个Python网站:Django实战分享

大家好,我是小李,目前在一家中型互联网公司担任后端技术负责人。今天我想和大家分享一下我当初是如何用 Django 搭建我的第一个 Python 网站的。
这个故事要回溯到我刚入行的时候。当时我们团队接到一个任务:开发一个内部使用的员工信息管理平台,用于记录员工的基本信息、部门归属、考勤记录等。时间紧任务重,前端由另一组同事负责,我们的任务是快速构建一个可运行的后台服务,并提供接口供前端调用。
那会儿我对 Web 开发还处于“听得多,做得少”的阶段,虽然了解一些 Flask 和 Tornado 的基础知识,但真正写过的东西也就几个练习项目。老大建议我试试 Django —— 毕竟它是“大而全”的代表,在企业级应用中非常常见。于是,我带着几分忐忑,开始了我的第一个 Django 实战之旅。
初识 Django:为什么选择它?
Django 在 Python 圈子里被誉为“电池已备”的框架,这意味着大多数常用的开发组件都已经内置好了。比如用户系统、ORM、模板引擎、中间件等,基本都帮你想到了。这对于一个新手来说简直是福音,省去了大量查找第三方库和集成的时间。
当时我们的需求并不复杂,但希望有一个稳定可靠的架构基础。最终决定使用 Django 是基于以下几点考虑:
- 自带 ORM:对数据库操作友好,避免直接写 SQL。
- MVT 架构清晰:方便分层设计,易于维护。
- 强大的 Admin 后台:可以快速搭建一个数据管理界面,对我们这种需要内部管理功能的项目非常实用。
- 社区活跃:遇到问题网上资料丰富,不愁找不到解决方案。
现在回看,这确实是个明智的选择。
项目背景与挑战
我们要做的项目是一个员工信息管理系统(Employee Management System),主要功能包括:
- 员工信息录入与展示
- 部门管理(查看/新增/编辑)
- 考勤记录上传和查询
- 用户权限控制(管理员、HR)
刚开始搭建环境时,我就遇到了几个棘手的问题:
1. 不知道如何组织项目结构
作为一个新手,一开始我不太清楚怎么划分 Django 的 App、Project 以及模块之间的关系。Django 的术语体系对我来说像是另一个世界:Project 是整个站点容器,App 是功能模块,还有 urls.py、views.py、models.py、settings.py 等文件的作用也需要一一理清。
解决方法: 通过官方文档和 GitHub 上的一些开源项目参考,我理解了最佳实践做法。后来我学会了将每个核心功能拆分为独立的 App(如 employees、departments、attendance),这样代码结构更清晰,也更容易复用和维护。
2. 数据模型设计不合理,导致后期修改困难
最开始我没有花太多时间思考数据库表结构的设计,导致后面频繁更改 model,迁移到最后差点搞崩溃了数据库迁移记录。
解决方法: 后来我养成了一个习惯:先画 ER 图,明确各个实体之间的关系。Django 提供的 ForeignKey、OneToOneField、ManyToManyField 虽然方便,但如果前期考虑不周,后期代价很大。
3. 接口设计不够 RESTful,前后端耦合严重
因为是给前端提供接口,我一开始图方便,用了一些页面渲染的逻辑返回 JSON 数据。结果每次前端一改结构,后端就得跟着调整。
解决方法: 后来我统一使用 Django REST framework(DRF)重构了所有的 API,把 view 改成了 APIView 形式,并遵循标准的 REST 风格。这样前后端分离之后,沟通顺畅多了。
实践过程:一步步搭建你的第一个网站
下面我来带你们一步步搭起自己的 Django 小网站。假设我们现在要做一个简单的“文章博客系统”,包含文章发布、展示、评论等功能。
第一步:安装 Django 并创建项目
pip install django
django-admin startproject myblog
cd myblog
python manage.py runserver
这个时候访问 http://localhost:8000,就能看到熟悉的欢迎页啦!
第二步:创建 App
按照惯例,我们将不同的业务拆分成不同的 App。比如:
python manage.py startapp blog
python manage.py startapp comments
记得把 app 加到 settings.py 的 INSTALLED_APPS 中。
第三步:设计数据模型(models)
以 blog/models.py 为例:
from django.db import models
from django.contrib.auth.models import User
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
执行迁移命令:
python manage.py makemigrations
python manage.py migrate
别忘了注册 admin 页面,方便调试和初期内容管理:
from django.contrib import admin
from .models import Article
admin.site.register(Article)
第四步:创建视图(views)
为了演示,我们可以写一个简单的首页视图,显示所有文章:
# blog/views.py
from django.shortcuts import render
from .models import Article
def index(request):
articles = Article.objects.all()
return render(request, 'blog/index.html', {'articles': articles})
然后配置 URL 映射:
# blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
别忘了主项目的 urls.py 也要 include:
# myblog/urls.py
from django.urls import path, include
urlpatterns = [
path('blog/', include('blog.urls')),
]
第五步:使用 Django Templates 渲染页面
创建 templates 目录并配置:
# settings.py
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
...
},
]
然后在 templates/blog/index.html 写一个简单的 HTML:
<h1>我的博客</h1>
<ul>
{% for article in articles %}
<li>{{ article.title }}</li>
{% endfor %}
</ul>
启动服务后访问 /blog/,你就能看到所有文章列表啦!
第六步:进阶:添加 REST API 支持
接下来我们可以用 DRF 创建 API。
安装:
pip install djangorestframework
添加到 INSTALLED_APPS。
创建序列化器:
# blog/serializers.py
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
创建 API View:
# blog/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Article
from .serializers import ArticleSerializer
class ArticleList(APIView):
def get(self, request):
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)

配置 API URL:
# blog/urls.py
from django.urls import path
from .views import index, ArticleList
urlpatterns = [
path('', index, name='index'),
path('api/articles/', ArticleList.as_view(), name='article-list'),
]
这个时候访问 /blog/api/articles/,你就能看到 JSON 格式的返回结果了。
是不是挺快就搭起来一个网站?这只是冰山一角,后续你可以加入认证、权限控制、缓存、日志监控等等。
实战中的“踩坑”经验
1. 数据库迁移出错怎么办?
有时候你会发现执行 makemigrations 出错,或者 migrate 失败。常见的原因有:
- 字段类型改了但没指定 default 或 blank
- 迁移历史冲突(多人协作时容易出现)
解决办法:
- 使用
--fake参数强制同步迁移状态 - 删除部分 migration 文件并重新生成(仅限开发环境)
2. DRF 权限配置混乱
刚开始我没太注意权限,结果前端随便调个接口都能访问。后来我明白了,必须显式定义权限类:
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class ArticleList(APIView):
permission_classes = [IsAuthenticatedOrReadOnly]
def get(self, request):
...
3. 性能瓶颈:N+1 查询问题
当多个外键关联的数据被访问时,可能会引发多次数据库查询。这时候要用 select_related 或 prefetch_related 来优化。
比如:
Article.objects.select_related('author').all()
生产上线前的经验总结
1. 使用 Gunicorn + Nginx 部署
Django 自带的 runserver 只适合本地调试,生产环境一定要换掉。我们常用的是:
- Gunicorn:轻量级 WSGI server
- Nginx:做反向代理,处理静态资源、负载均衡
Gunicorn 启动示例:
gunicorn --bind :8000 myblog.wsgi:application
Nginx 配置:
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /static/ {
alias /path/to/static_root/;
}
}
2. 静态资源收集
线上环境中,我们通常会设置:
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')
然后运行:
python manage.py collectstatic
这样可以把所有静态资源集中到一起,便于 Nginx 管理。
3. 日志配置不可忽视
生产环境的日志非常关键。推荐你在 settings.py 中加上完整的 logging 配置,输出到文件,定期备份。
4. 数据库备份策略
定期用 pg_dump 或其他工具导出数据库,防止意外情况丢失数据。
效果与收获
经过两周左右的奋战,我们的员工管理系统终于完成了第一版,顺利上线。系统运行稳定,响应速度也能满足内部需求。最让我欣慰的是,后续随着新需求的增加,系统也能比较灵活地扩展,比如新增审批流程、支持多种角色权限等。
更重要的是,这次实战让我真正理解了 Django 的整体架构和工作流,对整个 Web 开发链条也有了更清晰的认识。
给读者的一些建议
如果你也是刚入门 Django 的开发者,我有几点经验想分享:
不要急着上手写代码,先理清架构和流程
- 看几篇别人写的教程,自己动手搭个 Demo 玩玩
- 明白 MVT 是什么,URL 分发机制是怎么回事
合理划分模块,善用 App 拆分
- 把不同功能拆成多个 App,方便管理和测试
- 不要把所有逻辑塞在一个 App 里
重视数据库模型设计
- 设计模型时多想想字段之间关系
- 宁愿前期多花点时间,后期重构很痛苦
API 设计要规范
- 用 DRF 可以事半功倍
- 保持接口的通用性、一致性
部署上线不是小事
- 一定要测试部署流程
- 配置好日志、备份、权限、安全等环节
持续学习与迭代
- Django 社区发展很快,多关注更新和最佳实践
- 不妨看看源码,理解底层原理,帮助你写出更高效的代码
结语
Django 并不是一个难学的框架,相反,它非常“人性化”,只要你愿意多花些时间去理解和实践,它就会成为你开发路上的好伙伴。这篇文章只是抛砖引玉,真正的成长还是靠不断尝试、不断踩坑、不断总结。
希望这篇来自实战的第一人称经验分享,能给你带来些许启发。也欢迎大家在评论区交流,一起进步!
如有疑问或需要源码示例,欢迎留言,我会尽力回复!

评论 0