Django入门教程:搭建你的第一个Python网站

Issue终结者
2025-06-28 15:28
阅读 1750

初识 Django:我的第一个 Python 网站成长记

初识 Django:我的第一个 Python 网站成长记

大家好,我是某互联网公司的后端开发工程师,日常工作主要围绕高并发系统的架构与优化。说到 Django,我其实是从一个实际项目开始真正上手的——那时候我们团队要快速搭建一个内容管理平台(CMS),时间紧、任务重。老板说:“一周上线 Demo。” 同时,要求我们使用 Python 技术栈。

说实话,在那之前我对 Web 框架的理解还停留在“听过几个名词”的阶段,虽然知道 Flask 轻量,Tornado 异步,Django 全能,但没有深入实战过。最终选择 Django 的原因也很直接:它自带 ORM、Admin、用户权限体系、模板引擎……几乎把我们要用的功能都内置了。更重要的是,它的生态成熟、文档完善、社区活跃,对于我们这样的“临时拼装小队”来说,非常友好。

这篇文章就记录我从零到一搭建这个网站的过程,希望也能帮那些刚接触 Django 的小伙伴少走一些弯路。


项目背景:一次典型的内部系统开发

项目背景:一次典型的内部系统开发

我们需要做一个内部使用的 CMS 平台,主要功能是:

  • 支持多个编辑人员发布文章;
  • 文章需要分类、标签、审核状态等字段;
  • 需要有后台管理员界面,用于审核文章和管理用户;
  • 前端展示页面要做基础样式,不复杂但得像样;
  • 最关键的是,数据安全性不能忽视,哪怕这是个内部系统。

听起来需求不算特别复杂,但作为第一次独立使用 Django 的人,我还是踩了不少坑。下面我会从头讲起,尽量详细地记录每一步思考和实现过程。


项目搭建第一步:Django 初始化与结构规划

项目搭建第一步:Django 初始化与结构规划

安装环境

首先肯定是要安装 Django。我当时用的是 Python 3.9+pip。

pip install django==4.2.5

然后创建项目骨架:

django-admin startproject cms_project .

执行完成后,你会看到目录结构大概是这样的:

cms_project/
├── manage.py
└── cms_project/
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

接下来启动服务器:

python manage.py runserver

不出意外,就能访问 http://127.0.0.1:8000 看到 Django 默认的欢迎页。一切准备就绪!

创建 App 模块

在 Django 中,推荐将不同的功能拆分成多个 app。我们的 CMS 核心功能是文章管理,所以我新建了一个 articles app:

python manage.py startapp articles

同时别忘了在 settings.py 中添加这个 app 到 INSTALLED_APPS 列表里:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 我们自己的模块
    'articles',
]

数据库设计:安全与扩展性并重

既然要做 CMS,自然离不开数据库模型的设计。我一开始就决定使用 PostgreSQL,而不是默认的 SQLite。虽然本地开发可以先用 SQLite 快速验证,但一旦进入生产环境,还是更建议使用真正的关系型数据库。

配置数据库连接

修改 settings.py 中的 DATABASES 字段如下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'cms_db',
        'USER': 'cms_user',
        'PASSWORD': 'your_password',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

为了测试方便,我在本机搭了个简易的 PostgreSQL 实例,使用 Docker:

docker run --name some-postgres -e POSTGRES_USER=cms_user -e POSTGRES_PASSWORD=your_password -e POSTGRES_DB=cms_db -p 5432:5432 -d postgres

这样就可以快速拥有一个数据库服务。

模型设计

接下来就是定义 Article 数据模型,文件放在 articles/models.py

from django.db import models
from django.contrib.auth.models import User

class Category(models.Model):
    name = models.CharField(max_length=100)
    
    def __str__(self):
        return self.name

class Tag(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
    tags = models.ManyToManyField(Tag, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_published = models.BooleanField(default=False)  # 是否通过审核

    def __str__(self):
        return self.title

这里有几个值得说明的设计点:

  1. 用户与文章的关系:使用 Django 内建的 User 模型,省去自己造轮子;
  2. 外键约束:category 使用 on_delete=models.SET_NULL 来避免删除分类导致文章丢失;
  3. 多对多关系处理:tag 是一个典型的多对多字段;
  4. 软删除考虑:其实可以加一个 is_deleted 字段,不过这次因为时间紧张,暂时略过了,后面再升级;
  5. 安全意识体现:没有允许任何人随意删数据,而是通过状态字段控制是否显示。

生成迁移文件 & 同步数据库

写完 model 后,记得同步数据库:

python manage.py makemigrations
python manage.py migrate

这个时候你就可以登录数据库看看表是否已经正确建立起来了。


管理后台搭建:快速成型的神器

Django 自带 admin 功能,我们只需要注册模型即可快速拥有管理界面。

注册模型到 Admin

打开 articles/admin.py,添加以下代码:

from django.contrib import admin
from .models import Article, Category, Tag

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'created_at', 'is_published')
    list_filter = ('is_published', 'category', 'tags')
    search_fields = ('title', 'content')

admin.site.register(Category)
admin.site.register(Tag)

之后运行服务,访问 /admin 页面,可以看到已经出现对应的文章管理界面。

这时候我发现一个很现实的问题:默认的管理员后台对非技术人员不够友好。我们团队有部分产品经理也需要操作这个系统,他们并不熟悉 technical 字段,比如不知道怎么选分类,或者不知道“is_published”意味着什么。

改进:增加描述和友好的字段名

于是我对 Admin 类进行了调整:

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    list_display = ('标题', '作者', '创建时间', '已发布')
    list_filter = ('已发布', '分类', '标签')
    search_fields = ('标题', '内容')
    fieldsets = (
        (None, {'fields': ('标题', '内容')}),
        ('分类信息', {'fields': ('分类', '标签')}),
        ('状态控制', {'fields': ('已发布',)}),
    )

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)

    def save_model(self, request, obj, form, change):
        if not obj.pk:
            obj.author = request.user
        super().save_model(request, obj, form, change)

其中我还做了几点改进:

  • 给字段起中文名,提高可读性;
  • 对普通用户进行数据隔离,只能看到自己的文章;
  • 在保存时自动设置作者为当前用户。

这样一来,产品同学也能轻松上手了。


前端页面展示:模板 + 接口初探

我们虽然是后端主导,但作为一个完整的系统,前端展示当然也不能落下。

编写视图函数

articles/views.py 中新增一个展示文章列表的视图:

from django.shortcuts import render
from .models import Article

def article_list(request):
    articles = Article.objects.filter(is_published=True).order_by('-created_at')
    return render(request, 'articles/list.html', {'articles': articles})

接着配置 URL,在 urls.py 里加上路由:

from django.urls import path
from articles import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('articles/', views.article_list, name='article_list'),
]

然后创建 templates 目录,组织结构如下:

templates/
└── articles/
    └── list.html

list.html 文件内容大致如下:

<!DOCTYPE html>
<html>
<head>
    <title>文章列表</title>
</head>
<body>
<h1>已发布的文章</h1>
<ul>
    {% for article in articles %}
        <li><a href="#">{{ article.title }}</a></li>
    {% endfor %}
</ul>
</body>
</html>

访问 /articles/ 就能看到文章列表了。

接口设计初探

除了网页展示,我们还提供了 JSON 格式的接口供其他服务调用。最简单的做法是直接在 view 中返回 JsonResponse:

from django.http import JsonResponse
from .models import Article

def api_article_list(request):
    articles = Article.objects.filter(is_published=True).values('id', 'title', 'created_at')
    return JsonResponse(list(articles), safe=False)

URL 配置类似:

path('api/articles/', views.api_article_list),

但这种写法很快遇到了瓶颈:随着功能增多,手动处理参数校验、分页、排序变得非常麻烦。

于是我们改用 Django REST Framework(DRF)来做 API 层,这又是另一篇经验总结了。简单提一下,有了 DRF,我们可以定义 Serializers 和 ViewSets,极大地提升了 API 开发效率,也更容易做权限控制。


上线部署:生产环境的小细节

使用 Gunicorn + Nginx 部署

开发完成之后,我们准备上线测试版。我选择了比较常规的方案:Gunicorn 作为 WSGI server,Nginx 反向代理。

安装依赖:

pip install gunicorn

然后在项目根目录下新建 gunicorn.conf.py

bind = "127.0.0.1:8001"
workers = 3
timeout = 60
accesslog = "/var/log/cms/gunicorn_access.log"
errorlog = "/var/log/cms/gunicorn_error.log"
capture_output = True
loglevel = "info"

启动命令:

gunicorn -c gunicorn.conf.py cms_project.wsgi

Nginx 配置如下(简化版):

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /static/ {
        alias /path/to/static/;
    }
}

别忘了收集静态文件:

python manage.py collectstatic

安全注意事项

部署的时候我也犯过几个错误,分享给大家:

  1. DEBUG 设置未关闭:Django 默认开启 DEBUG 模式,上线时必须设置 DEBUG=False,否则会泄露敏感信息;
  2. Secret Key 暴露:不要硬编码在 settings.py 中,最好从环境变量中读取;
  3. CSRF 和 Session 设置:特别是跨域请求和 Cookie 安全相关;
  4. 权限最小化:数据库账号应该只具备必要权限;
  5. 日志监控:部署后务必监控日志,及时发现异常请求或报错。

总结与感悟:从一个小网站学到的大道理

现在回头看,那个“一周上线 Demo”的目标,实际上花了整整三周才勉强完成。并不是功能有多复杂,而是在真实的工作场景中,总会遇到各种意料之外的小问题:

  • 第一天:连数据库都连不上,是因为 PostgreSQL 的权限配置没搞定;
  • 第三天:前端渲染一直出错,原来是缓存太强,强制刷新没反应;
  • 第五天:上线之后突然数据库连接池爆满,被迫紧急加索引;
  • ……

但正是这些看似零碎的小事,才让我真正理解了一个“完整网站”的构建过程:不只是写几个 model 和 view,更重要的是要考虑稳定性、安全性、性能、可维护性。

如果你也在入门 Django,以下几个建议送给你:

  1. 从模仿开始,但不要盲从:官方文档是最好的老师,但一定要动手敲一遍,不能只看不动;
  2. 多看源码:Django 代码质量非常高,看懂一些内部机制会让你受益匪浅;
  3. 注意安全性,早些养成习惯:很多新手忽略 XSS、CSRF、SQL 注入等问题,结果上线后漏洞频出;
  4. 合理利用内置功能,别重复造轮子:尤其是权限管理、Admin、ORM 这些模块,能节省大量时间;
  5. 提前考虑部署问题:不要等到“上线前夜”才发现无法部署;
  6. 写好注释和文档,给未来的自己留条活路:代码易读性非常重要。

结语

这篇文字与其说是教程,不如说我在这段时间工作的“个人成长笔记”。也许你正在尝试学 Django,也许你在工作中也遇到过类似的挑战。无论你是初学者,还是想深入了解 Python Web 开发,我都希望这篇经历能对你有所帮助。

最后,愿每一个认真写代码的人,都能写出又快又好、安全可靠的系统。共勉!

评论 0

最热最新
暂无评论
Issue终结者Lv.1
0
影响力
0
文章
0
粉丝