用Django搭个网站,比改需求还简单?

温文尔雅
2025-12-28 01:38
阅读 415

上周五晚上十点半,我瘫在工位上盯着屏幕上产品经理刚甩过来的PRD——“做一个基于区块链的用户积分系统原型,下周三演示”。当时我差点把手里那杯瑞幸捏爆。我们是外包公司,不是创业孵化器啊!更离谱的是,这项目连UI稿都没给全,就一句“先跑起来看看效果”。

但没办法,甲方爸爸的需求就是圣旨。作为在魔都某不知名外包公司摸爬滚打四年的老油条,我深知:与其抱怨,不如动手。反正VSCode里Python插件早就装好了,Django环境也配过八百遍。索性趁着周末,从零搭个最简版网站出来,至少能把“能跑”这个底线守住。

顺便说一句,最近面试季,好几个兄弟问我“Django和Flask区别是啥”,甚至有HR直接甩来一道面试题:“如何用Django实现一个简单的REST API?” 所以今天这篇,既是实战记录,也算给后来人铺点路。


为啥选Django?因为快!

我知道有人会说:“现在都2024年了,还用Django?不上FastAPI或者Go吗?” 兄弟,醒醒!我们是外包,不是字节。客户要的是快速交付、能跑就行、别崩就行。Django自带Admin后台、ORM、用户认证、安全防护(CSRF、XSS等),开箱即用。你让我三天内搞定一个带登录、增删改查的后台,我选Django闭着眼都能写完。

而且Python语法简洁,团队里新人上手快。上次实习生小李,学了两天就能改views.py,虽然把数据库migration搞炸了一次,但总比让他啃Spring Boot强。


环境搭建:别被pip坑了

首先,确保你装了Python 3.8+(推荐3.10)。我用的是pyenv管理版本,但如果你图省事,直接官网下也行。

# 创建虚拟环境(强烈建议!)
python -m venv django_env
source django_env/bin/activate  # Linux/Mac
# django_env\Scripts\activate  # Windows

# 安装Django
pip install django

血泪教训:千万别全局装包!我去年双11前上线一个项目,就因为没用虚拟环境,pip upgrade把系统依赖搞乱了,服务器直接502,运维大哥差点提刀来找我。

验证安装:

django-admin --version
# 输出类似:4.2.7

创建你的第一个项目

Django的“项目”(project)和“应用”(app)是两个概念。项目是整体容器,应用是功能模块。比如一个电商网站,项目叫shop_project,里面可能有user_apporder_appproduct_app等。

django-admin startproject mysite
cd mysite
python manage.py runserver

访问 http://127.0.0.1:8000,看到那个火箭图标了吗?恭喜,你已经打败了全国90%的还没开始的人。


加个App:从Hello World到真实业务

光看欢迎页没用,得干点正事。我们按客户要求,先做个“用户积分记录”页面。虽然他说要“区块链”,但咱先做传统数据库版,后面再忽悠他“底层已预留区块链接口”(手动狗头)。

python manage.py startapp points

然后在mysite/settings.py里注册这个app:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'points',  # ← 加这一行
]

设计模型:别一上来就搞复杂

客户说“积分要可追溯、不可篡改”,听着像区块链特性。但我们先别被唬住——外包的第一原则:用最简单的方式满足表面需求

所以模型就这么设计:

# points/models.py
from django.db import models
from django.contrib.auth.models import User

class PointRecord(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    amount = models.IntegerField()  # 正为增加,负为扣除
    reason = models.CharField(max_length=200)  # 比如“签到奖励”、“兑换商品”
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return f"{self.user.username}: {self.amount} ({self.reason})"

注意:这里用了Django内置的User模型,省去了自己写注册登录的麻烦。外包讲究效率,重复造轮子?不存在的。

生成并执行迁移:

python manage.py makemigrations
python manage.py migrate

写个视图:别怕CBV,FBV也香

Django支持函数视图(FBV)和类视图(CBV)。我一般小项目用FBV,清晰直白;大项目用CBV,复用性强。

先来个简单的列表页:

# points/views.py
from django.shortcuts import render
from .models import PointRecord

def point_list(request):
    records = PointRecord.objects.all().order_by('-created_at')
    return render(request, 'points/list.html', {'records': records})

配个URL:

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

urlpatterns = [
    path('', views.point_list, name='point_list'),
]

别忘了在主urls里include:

# mysite/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('points/', include('points.urls')),
]

模板:别追求花里胡哨

外包前端?不存在的。我们用Django模板凑合一下就行。创建points/templates/points/list.html

<!DOCTYPE html>
<html>
<head>
    <title>积分记录</title>
</head>
<body>
    <h1>所有积分变动</h1>
    <ul>
    {% for record in records %}
        <li>{{ record.created_at|date:"Y-m-d H:i" }} - 
            {{ record.user.username }}: {{ record.amount }} ({{ record.reason }}})
        </li>
    {% empty %}
        <li>暂无记录</li>
    {% endfor %}
    </ul>
</body>
</html>

启动服务,访问 /points/,看到数据了吗?如果没有,去/admin/加几条测试数据。

提示:先创建超级用户:python manage.py createsuperuser,然后登录admin后台,你会发现PointRecord自动出现在管理界面——这就是Django Admin的魔法。


关于“区块链”的真相

回到开头那个需求。客户嘴里的“区块链”,大概率只是想要“数据不可篡改 + 可追溯”。其实在传统数据库里,只要做到以下几点,也能满足:

  1. 禁止物理删除:用is_deleted字段软删除
  2. 记录操作日志:每次变更都留痕
  3. 关键字段只增不减:比如积分余额,只通过原子操作更新

真要上链?成本太高,运维复杂,还不一定有用。我跟客户说:“我们用Django的审计日志 + 时间戳 + 数字签名,效果一样,还能快速上线。” 他居然信了。

面试时如果被问“如何结合区块链”,你可以答:“Django负责业务逻辑和API,区块链作为底层存储或验证层,通过智能合约交互。但需评估性能和成本。” —— 这话术,稳!


性能与架构:别等上线才优化

虽然这是demo,但我习惯一开始就考虑生产环境。几个建议:

1. 数据库查询优化

上面的point_list视图有个N+1问题:每条记录都要查一次user。应该用select_related

records = PointRecord.objects.select_related('user').order_by('-created_at')

2. 分页必须加

万一条数多了,页面直接卡死。Django自带Paginator:

from django.core.paginator import Paginator

def point_list(request):
    records = PointRecord.objects.select_related('user').order_by('-created_at')
    paginator = Paginator(records, 20)  # 每页20条
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    return render(request, 'points/list.html', {'page_obj': page_obj})

模板里加个分页导航就行。

3. 静态文件与部署

开发时Django自动托管静态文件,但生产环境必须用Nginx。我在上海租房,家里宽带上传慢,所以常用Gunicorn + Nginx部署到阿里云轻量服务器,月付60块搞定。

# 安装Gunicorn
pip install gunicorn

# 启动
gunicorn mysite.wsgi:application --bind 0.0.0.0:8000

配合Nginx反向代理,加个SSL证书(Let's Encrypt免费),一套下来不到两小时。


常见坑 & 面试题答案

这些年踩过的坑,总结成几道高频面试题

问题 我的回答
Django ORM怎么防止SQL注入? 自动参数化查询,不用原生SQL就基本安全
如何处理并发积分扣减? 用F表达式 + 事务,例如 PointRecord.objects.filter(user=user).update(balance=F('balance') - 10)
settings.py里的SECRET_KEY能放代码仓库吗? 绝对不行!用环境变量或配置文件分离
为什么用Django不用Flask? 快速交付场景下,Django的“全栈”特性减少集成成本

最后:外包程序员的生存之道

说到底,我们不是在写艺术,是在交活儿。Django之所以适合外包,是因为它让你少写代码、少背锅、快交付。至于区块链?等客户真愿意为技术买单再说吧。

上周三演示时,客户看着那个朴素的积分列表,居然点头说“有内味了”。我心想:这哪是区块链,这明明是“糊弄学+Django”的胜利。

不过话说回来,能用简单技术解决复杂问题,才是真本事。下次再有人问“Django过时了吗?”,你就反问:“你的需求,需要微服务+K8s+Service Mesh吗?”

如果不是,那就老老实实用Django,早点下班,回家打游戏。


附:我的VSCode Django开发插件清单(亲测好用)

  • Python(官方)
  • Django(Baptiste Darthenay)
  • Pylance
  • GitLens
  • REST Client(测试API超方便)
  • indent-rainbow(对齐强迫症福音)

就这样,希望这篇带点烟火气的教程,能帮你少熬几个夜。毕竟,在上海,房租那么贵,命得省着点用。

评论 0

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