从零开始用Django搭网站:一位后端程序员的成长之路

工程师的半亩地
2025-06-12 23:27
阅读 699

引言:为什么选择Django?

引言:为什么选择Django?

还记得两年前,我刚转行做后端开发的时候,公司安排了一个任务:在两周内,独立完成一个内部使用的资产管理系统。作为一个Python新手,我第一反应是——“这玩意儿怎么上手?有没有现成的框架?”这时候,前辈推荐了Django:“它功能齐全、文档完善,适合快速搭建功能完整的网站。”

说实话,当时我对这个框架几乎一无所知,只知道它是Python界的老牌Web框架。但随着项目的推进,我才真正体会到它的强大之处。这篇文章就想结合那次项目经历,聊聊我是如何从0到1用Django搭建第一个网站,以及其中踩过的那些坑和收获的经验。

项目背景:内部资产管理系统的需求

项目背景:内部资产管理系统的需求

我们公司是一个中型互联网团队,之前很多资产管理流程都是靠Excel手工操作,效率低不说,还容易出错。于是领导决定做一个轻量级系统来统一管理电脑、服务器、网络设备等资源信息。

功能需求包括:

  • 用户登录(权限控制)
  • 资产分类与展示
  • 添加/编辑/删除资产
  • 模糊搜索和列表过滤
  • 简单的数据统计(资产状态分布)

目标用户主要是公司IT运维同事和部分管理层,对系统的性能和并发要求不高,但希望界面清晰、操作流畅。


初期尝试:选型对比

初期尝试:选型对比

最初我也想试试其他轻量级框架比如Flask或者FastAPI,但很快发现,对于一个刚入行的人来说,要自己实现用户认证、后台模板、表单处理这些通用功能,学习成本太高。

而Django正好是一站式解决方案。它自带了用户系统、数据库ORM、Admin后台、模板引擎、安全防护等等,几乎是开箱即用。虽然灵活性略逊于Flask,但在快速开发的前提下非常合适。

最后我还是选择了Django,作为我的首次实战项目。


遇到的第一个挑战:环境搭建不顺利

刚开始的时候遇到几个典型问题:

系统架构设计图-2

问题1:pip install django 安装失败

第一次安装时,执行pip install django报错一堆依赖冲突,后来才知道是虚拟环境没配好。

解决办法:强烈建议使用python -m venvvirtualenv创建独立虚拟环境,并激活后再安装Django。

# 创建并激活虚拟环境
python3 -m venv env
source env/bin/activate  # Linux/Mac
env\Scripts\activate     # Windows

然后安装稳定版本的Django(以4.2为例):

pip install "django==4.2"

📌 小提示:不要盲目追新版本,除非你确实需要某些高级特性,否则建议使用LTS(长期支持)版,避免踩兼容性坑。

问题2:运行runserver时报错找不到模块

有时候新建完项目启动服务时会遇到类似这样的错误:

ModuleNotFoundError: No module named 'django.core'

解决办法:确认是否忘记激活虚拟环境,或者Django没有正确安装。可以用 pip list 查看当前环境是否已包含Django库。


建模设计:数据库结构是关键

接下来是最核心的一部分:数据模型的设计。

根据需求,我们需要记录资产的基本信息,比如:

  • 名称、类型、SN号、购买时间、负责人、当前状态等。

所以我定义了一个名为Asset的模型:

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

class Asset(models.Model):
    CATEGORY_CHOICES = [
        ('computer', '电脑'),
        ('server', '服务器'),
        ('network', '网络设备'),
        ('other', '其他'),
    ]

    STATUS_CHOICES = [
        ('in_use', '在用'),
        ('idle', '闲置'),
        ('repair', '维修'),
        ('disposed', '报废'),
    ]

    name = models.CharField('名称', max_length=100)
    category = models.CharField('类别', max_length=50, choices=CATEGORY_CHOICES)
    sn = models.CharField('序列号', max_length=100, unique=True)
    purchase_date = models.DateField('采购日期')
    owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name='负责人')
    status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES)

    def __str__(self):
        return self.name

这里需要注意几点:

  • 使用choices字段可以简化下拉框选项
  • 外键关联User表实现了权限控制的基础
  • unique=True防止重复录入资产编号
  • 每个字段都加了中文verbose_name,便于Django Admin显示

在数据库方面,Django默认使用SQLite,但对于生产环境来说不太合适。我后来换成PostgreSQL,原因如下:

  • 支持更复杂的查询、事务机制
  • Django ORM对其优化更好
  • 后续可能有大数据迁移计划

路由与接口设计:前后端交互的关键

路由和视图设计上,我采取前后端混合的方式,因为这次项目不需要复杂前端,使用Django内置的模板系统即可满足需求。

不过为了方便后期扩展REST API,我在urls.py里做了统一规划:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.asset_list, name='asset_list'),
    path('add/', views.asset_add, name='asset_add'),
    path('<int:pk>/edit/', views.asset_edit, name='asset_edit'),
    path('<int:pk>/delete/', views.asset_delete, name='asset_delete'),
    
    # 新增接口用于前端AJAX调用
    path('api/list/', views.AssetListView.as_view(), name='api_asset_list'),
]

同时我采用类视图方式编写接口逻辑,方便后续维护和复用:

# views.py
from django.views.generic import View
from django.http import JsonResponse

class AssetListView(View):
    def get(self, request):
        assets = Asset.objects.all()
        data = list(assets.values('id', 'name', 'category', 'status'))
        return JsonResponse(data, safe=False)

数据流转过程-1

⚠️ 注意点:JSON响应要用.values()取值并转成list,才能被Django的JsonResponse接受。


开发过程中的真实“踩坑”记录

下面分享几个让我印象深刻的坑和对应的解决经验,希望能帮你在开发过程中少走弯路。


坑1:静态文件加载不出来

开发后台页面的时候,引入CSS和JS始终加载失败,页面样式混乱。

排查步骤

  1. 检查settings.py中STATIC_URL配置是否正确
  2. 把静态文件放在static目录下,并在HTML中使用 {% static %} 加载
{% load static %}
<link rel="stylesheet" href="{% static 'css/main.css' %}">
  1. 运行collectstatic命令收集静态文件(部署时必须运行)
python manage.py collectstatic

坑2:Admin自定义太难?

Django自带的admin系统很方便,但如果直接暴露所有字段给运维同事,显得太原始。我想做个自定义页面,展示资产统计数据。

解决思路: 继承ModelAdmin,自定义页面模板,添加统计面板。

from django.contrib import admin
from .models import Asset
from django.db.models import Count
from django.utils.html import format_html

@admin.register(Asset)
class AssetAdmin(admin.ModelAdmin):
    list_display = ['name', 'sn', 'category', 'status']
    list_filter = ['category', 'status']

    change_list_template = "admin/asset_change_list.html"

    def changelist_view(self, request, extra_context=None):
        response = super().changelist_view(request, extra_context=extra_context)
        try:
            queryset = response.context_data['cl'].queryset
        except (AttributeError, KeyError):
            return response

        stats = {
            'total': queryset.count(),
            'used': queryset.filter(status='in_use').count(),
            'idle': queryset.filter(status='idle').count(),
        }

        response.context_data['stats'] = stats
        return response

然后在templates/admin/asset_change_list.html中就可以渲染对应的数据。


坑3:用户权限判断写死了?

最开始我在每个视图里都手动判断用户是否登录和是否有权限,后来代码越来越乱,而且权限判断分散在各个地方,难以维护。

解决方案:使用装饰器+中间件统一处理权限逻辑

from functools import wraps
from django.shortcuts import redirect

def login_required(view_func):
    @wraps(view_func)
    def wrapped_view(request, *args, **kwargs):
        if not request.user.is_authenticated:
            return redirect('login')
        return view_func(request, *args, **kwargs)
    return wrapped_view

然后在需要的视图前加上装饰器:

@login_required
def asset_add(request):
    ...

这样权限判断就统一起来了。


上线部署:别忽视生产环境的细节

项目本地测试没问题,但上线时又遇到了几个新问题。


部署环境说明:

  • 主机:阿里云ECS,CentOS 7
  • Web服务器:Nginx + Gunicorn
  • 数据库:PostgreSQL
  • 域名解析:绑定到了一个二级域名 asset.internal.xxx.com

问题1:Gunicorn启动失败,日志为空

一开始照着网上教程配置gunicorn,结果启动失败,但没有任何输出。

解决方法

  • 查看gunicorn是否以daemon模式运行,需要指定--log-file参数
gunicorn myproject.wsgi:application --bind 0.0.0.0:8000 --daemon --log-file /var/log/gunicorn.log
  • 也可以先不加daemon运行看看前台输出日志

问题2:Nginx代理设置错误,导致访问路径不对

前端请求 /static/ 路径的资源,返回404。

配置示例

server {
    listen 80;
    server_name asset.internal.xxx.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/;
    }
}

⚠️ 特别注意:这里的/path/to/static_root/必须和settings.py中的STATIC_ROOT保持一致,也就是运行过collectstatic后的目录位置。


问题3:数据库连接超时

项目上线初期经常出现数据库连接异常。

排查结果: 原来是数据库连接池没有合理配置,每次请求都重新建立连接。后来加上了dj-database-url配合连接池插件psycopg2-binary解决了这个问题。

# settings.py

import dj_database_url

DATABASES = {
    'default': dj_database_url.config(
        default='postgres://user:password@localhost:5432/dbname',
        conn_max_age=600
    )
}

最终效果:系统稳定上线,效率提升显著

经过近三周的努力,系统终于上线运行。从最初的磕磕绊绊,到最终流畅运行,整个过程让我深刻体会到了Django在中小型项目上的优势。

  • 提升了IT部门的资产管理效率,原本需要半小时的录入工作现在几分钟就能完成
  • 实现了简单的权限划分,普通用户只能查看资产列表,管理员可进行编辑和删除
  • 页面简洁直观,用户反馈良好

更重要的是,通过这个项目,我掌握了:

  • Django项目的整体架构设计
  • ORM的高级用法
  • 权限控制的实现
  • 接口和页面的整合
  • 前端与后端协作的实践
  • 生产环境部署和调试技巧

给新手的一些建议与经验总结

如果你也是刚接触Django的新手,以下是我走过弯路后的一些心得总结:


✅ 建议1:从官方文档起步,别急着抄别人的项目

很多人喜欢直接搜“Django博客系统”,结果越学越懵。建议老老实实读一遍Django官方教程,了解MTV架构、模型定义、URL映射、模板渲染这些基础概念。


✅ 建议2:善用Django Admin,它比你想象中强大

很多人觉得Admin只是后台管理工具,其实可以通过重写模板、添加自定义列、集成统计图表等方式,把它打造成强大的业务平台。


✅ 建议3:多用装饰器或中间件解耦业务逻辑

权限验证、日志记录、性能监控都可以通过中间件和装饰器统一处理,减少视图函数的臃肿。


✅ 建议4:数据库设计尽量提前考虑扩展性

虽然Django的迁移机制很友好,但在设计模型时,最好预留一些扩展字段或者通过外键关联来应对未来变化。


✅ 建议5:上线前务必压测!

即便是一个小系统,在高并发下也可能暴露性能瓶颈。可以通过Locust等工具模拟压力测试,检查慢SQL、缓存命中率等问题。


写在最后:Django依旧是你值得掌握的技术栈之一

这两年Django在国内的热度似乎不如Go语言那么火,但我始终觉得它在一个成熟的Web开发体系中有着不可替代的优势:

  • 成熟稳定的生态
  • 社区活跃,文档丰富
  • 快速交付的能力
  • 强大的ORM能力
  • 合理的工程组织方式

尤其对于初创项目或企业内部落地的小系统,Django仍是首选框架之一。

如今再回头看看那个第一次写出来的资产系统,虽然简单,却是我职业生涯中一次重要的成长转折点。愿这篇文字能给你带来些许启发,也欢迎在评论区交流你的Django学习故事。

共勉之!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝