从写爬虫到搭网站:一个考公程序员的Django初体验

◆李敏
2025-12-23 16:11
阅读 2242

上周五晚上十点半,我盯着 VSCode 里满屏的 Go 后端日志,突然意识到一个问题:我这个天天和算法、高并发打交道的“资深”后端码农,居然连个像样的个人网站都没有。

事情的起因其实有点搞笑。我们组最近在搞一个内部数据可视化项目,产品经理拍脑袋说:“要不咱们用 Django 搭个前端展示页面吧,Python 简单,你不是之前写过爬虫吗?”
我内心翻了个白眼——爬虫是爬虫,Web 是 Web,这能一样?但嘴上还是应了下来,毕竟离省考还有三个月,领导看我复习资料的眼神已经不太友善了,得表现得“积极工作”一点。

于是,抱着“速战速决,赶紧回去刷行测”的心态,我花了周末两天时间,硬是把人生第一个 Django 网站跑起来了。过程中踩了不少坑,也顺手整理了这篇记录,算是给未来的自己(以及同样想快速上手 Django 的兄弟)留个路标。


为啥是 Django?不是 Flask,也不是 Go?

先别急着喷我技术选型保守。其实在公司,我们的主力后端语言是 Go —— 高性能、并发强、部署轻量,非常适合我们这种每天要处理百万级请求的系统。但这次不一样:需求简单、交付快、还要兼容我那点 Python 老底子

我大学时搞过一段时间爬虫,用的就是 Python + requests + BeautifulSoup,后来实习还写过基于 Scrapy 的分布式采集框架。所以对 Python 生态不算陌生。而 Django 作为“全栈式”Web 框架,自带 ORM、Admin、用户认证、路由系统,开箱即用,特别适合快速原型开发。

相比之下:

  • Flask 太轻量,啥都要自己配,适合微服务,但不适合“赶工”;
  • Go 的 Gin/Echo 虽然快,但 HTML 渲染、模板继承这些玩意儿写起来不如 Django 优雅;
  • Node.js?算了,前端同事已经够卷了,我不想再碰 JS 生态。

所以,Django 成了最合理的选择——哪怕它被某些性能控嘲讽为“笨重”,但对我这个只想“搭个页面交差+顺便学点新东西”的在职考生来说,开发效率 > 极致性能


环境搭建:VSCode + Django = 舒服!

作为一个 VSCode 死忠粉,插件装了一堆:Python、Pylance、Django、Bracket Pair Colorizer、GitLens……启动项目前,先确保环境干净:

# 创建虚拟环境(强烈建议!别污染全局)
python -m venv djangosite_env
source djangosite_env/bin/activate  # Linux/Mac
# djangosite_env\Scripts\activate   # Windows

# 安装 Django
pip install django

# 验证安装
django-admin --version  # 输出类似 4.2.7

然后新建项目:

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

浏览器打开 http://127.0.0.1:8000,看到那个经典的火箭图标——成了!那一刻,我甚至有点感动,仿佛回到了大二第一次跑通 Hello World 的夜晚。

💡 小贴士:如果你用 VSCode,记得在 .vscode/settings.json 里指定 Python 解释器路径,不然调试会出问题。我上次就是因为没设,debug 时一直报 ModuleNotFoundError,差点砸键盘。


从“Hello World”到真实业务:建个文章发布系统

光看默认页面当然不够。产品经理的需求其实是:“展示最近抓取的行业新闻”。这不就是我老本行——爬虫 + 展示?

第一步:设计模型(Model)

Django 的 ORM 真香!不用写 SQL,用 Python 类定义表结构:

# mysite/news/models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    source_url = models.URLField()
    published_at = models.DateTimeField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

这里我加了 published_at(新闻发布时间)和 created_at(入库时间),方便后续排序。字段类型也很直观:CharField 对应 VARCHAR,TextField 是长文本,URLField 自带校验。

第二步:注册 Admin,手动录入测试数据

Django 自带的 Admin 后台简直是懒人福音:

# mysite/news/admin.py
from django.contrib import admin
from .models import Article

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title', 'published_at', 'created_at')
    search_fields = ('title',)

然后执行迁移:

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser  # 按提示输入用户名密码

启动服务后,访问 /admin,登录,就能看到一个功能完整的后台!我手动加了几条假数据,瞬间有了“产品上线”的错觉。

🤦‍♂️ 踩坑记录:第一次忘了执行 makemigrations,直接 migrate,结果表没建。报错 Table "news_article" does not exist。这种低级错误,在 deadline 压力下真的会发生!


写视图(View)和模板(Template):让数据动起来

现在要把数据库里的文章展示到首页。

视图函数

# mysite/news/views.py
from django.shortcuts import render
from .models import Article

def home(request):
    articles = Article.objects.order_by('-published_at')[:10]  # 最新10条
    return render(request, 'news/home.html', {'articles': articles})

URL 路由

# mysite/news/urls.py
from django.urls import path
from . import views

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

别忘了在主 urls.py 里 include:

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

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

模板渲染

Django 模板语法简洁明了:

<!-- mysite/news/templates/news/home.html -->
<!DOCTYPE html>
<html>
<head>
    <title>行业快讯</title>
</head>
<body>
    <h1>最新文章</h1>
    {% for article in articles %}
        <div>
            <h2>{{ article.title }}</h2>
            <p>{{ article.content|truncatewords:30 }}</p>
            <small>发布时间: {{ article.published_at }}</small>
            <a href="{{ article.source_url }}">原文链接</a>
        </div>
        <hr>
    {% empty %}
        <p>暂无文章</p>
    {% endfor %}
</body>
</html>

刷新页面,数据出来了!那一刻,我真的笑出了声——虽然只是个静态列表,但这是我亲手搭建的第一个完整 Web 应用


性能优化?先别急,但得有意识

作为对性能敏感的后端程序员,我忍不住想:如果文章量涨到 10 万条,Article.objects.all() 会不会把 DB 干崩?

Django 提供了多种优化手段:

优化方式 说明 适用场景
select_related 一对一/外键预加载 减少 N+1 查询
prefetch_related 多对多/反向关系预加载 关联查询优化
分页 (Paginator) 避免一次性加载大量数据 列表页必备
数据库索引 published_at 上加索引 加速排序和过滤

比如,加索引:

class Article(models.Model):
    # ...
    published_at = models.DateTimeField(db_index=True)  # 关键!

再比如分页:

from django.core.paginator import Paginator

def home(request):
    article_list = Article.objects.order_by('-published_at')
    paginator = Paginator(article_list, 10)  # 每页10条
    page_number = request.GET.get('page')
    articles = paginator.get_page(page_number)
    return render(request, 'news/home.html', {'articles': articles})

这些改动成本极低,但能极大提升可扩展性。写代码时多想一步,线上就少一次 P0 事故——这是我们组长常说的话。


和爬虫联动:自动化填充数据

既然我擅长爬虫,那就写个脚本自动抓数据入库!

# scripts/fetch_news.py
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
django.setup()

from news.models import Article
import requests
from bs4 import BeautifulSoup
from datetime import datetime

def scrape_and_save():
    url = "https://example-news-site.com"
    res = requests.get(url)
    soup = BeautifulSoup(res.text, 'html.parser')
    
    for item in soup.select('.news-item'):
        title = item.select_one('.title').text
        content = item.select_one('.content').text
        link = item.select_one('a')['href']
        
        # 避免重复
        if not Article.objects.filter(source_url=link).exists():
            Article.objects.create(
                title=title,
                content=content,
                source_url=link,
                published_at=datetime.now()
            )

if __name__ == "__main__":
    scrape_and_save()

然后用 crontab 定时执行:

# 每天上午9点抓一次
0 9 * * * /path/to/venv/bin/python /path/to/scripts/fetch_news.py

完美!现在我的小网站不仅能展示数据,还能自动更新。虽然比不上公司里用 Kafka + Flink 的实时管道,但对个人项目来说,够用了


为什么我这个 Go 后端要学 Django?

可能有人会问:你不是准备考公吗?干嘛还折腾这些?

原因有三:

  1. 技术广度:公务员考试中的“计算机专业知识”部分,Web 开发是重点。理解 MVC、HTTP、数据库交互,比死记硬背概念有用得多。
  2. 简历加分:哪怕上岸了,技术背景也是优势。很多政务系统正在数字化,懂前后端的人才吃香。
  3. 保持手感:每天刷题很枯燥,写点代码能调节心态。而且 Django 的开发体验真的很治愈——那种“所想即所得”的流畅感,是 Go 里写 middleware 和 context 时体会不到的。

当然,我也清楚 Django 不适合所有场景。如果未来要做高并发 API 网关、实时推荐引擎,肯定还是 Go + Redis + Kafka 更合适。但在快速验证想法、搭建 MVP、做数据展示这类任务上,Django 依然是王者。


写在最后:从程序员到准公务员的跨界思考

搭完这个网站,我突然意识到:无论是写算法、调 Go 服务、写爬虫,还是现在玩 Django,核心能力其实是相通的——解决问题的逻辑 + 快速学习的能力

考公路上,很多人劝我“别碰代码了,专心背书”。但我偏不。因为我知道,真正的竞争力,从来不是单一技能,而是跨界整合的能力

下周我就要去参加行测模考了。但今晚,我决定再给这个小网站加个搜索功能——用 Django 的 icontains 实现全文检索。毕竟,梦想还是要有的,万一上岸后被分到信息中心,还能用上呢?


作者:某大厂后端程序员,白天调优 Go 服务,晚上刷行测真题,周末研究 Django。目标:2024年省考上岸。
GitHub:懒得放(怕被同事发现我在摸鱼)
本文所有代码均在本地测试通过,生产环境请务必加缓存、限流、日志监控——别学我,我可是被运维追着骂过的人 😅

评论 0

最热最新
暂无评论
◆李敏Lv.1
0
影响力
0
文章
0
粉丝