考试通知
1. 项目概览与需求拆解这两年乡村文旅和数字乡村的建设热度一直不减各地都在想办法把乡村风貌、特产、民俗文化搬到线上。我做的这个“农村综合风貌展示平台”本质上就是一套基于 Django 框架和 Python 语言开发的内容管理和展示系统核心目标是把一个村镇的自然资源、人文历史、产业特色、文旅路线整合到一个可访问、可维护、可扩展的网站上。先说说为什么要用“综合风貌”这个词。最早跟某乡镇的工作人员聊需求时对方提的是“做个官网就行”但细聊下来发现他们要展示的东西非常杂有村容村貌照片、有农产品介绍、有节日活动记录、还要发布通知公告。如果只用静态页面堆 HTML改一次内容就要找一次开发者根本跑不动。所以这个平台真正的定位是“内容管理系统加前端展示”让乡镇自己的工作人员就能更新页面内容而不是每次改动都依赖技术人员。从技术角度看这个项目的核心需求可以拆成四块。第一块是内容管理管理员要能方便地录入村庄介绍、图片图集、农产品信息、活动记录第二块是前端展示访客要能按分类浏览这些内容界面要美观移动端要友好第三块是检索能力访客能通过关键词快速找到某个农产品或某条旅游路线第四块是运维友好代码结构要清晰部署要简单服务器配置要求不能太高。这套需求用 Python 生态里的 Django 来做非常合适。Django 自带 ORM 映射、模板引擎、Admin 后台、表单处理和用户认证几乎把内容管理系统需要的基础设施都内置好了。相比 Flask 这类轻量框架Django 对这类“功能多、结构清晰、需要后台管理”的项目开发效率高出一大截。我在选型时也考虑过直接用现成的 CMS 系统但那些系统一是定制成本高二是后续想加地图、数据统计等功能会很别扭。自己用 Django 写一套前期多花点时间后期扩展反而顺手。这个项目的目标读者有两类。一类是刚学完 Django 基础、想找一个完整项目练手的学生或转行者另一类是乡镇信息化建设中需要快速搭一个内容管理平台的基层技术人员。前者可以把它当作一个标准的企业级开发案例来学习后者可以理解整体架构后直接复用代码框架。2. 技术选型与架构设计2.1 为什么选 Django 而不是其他框架做这个项目之前我专门对比过几种常见方案。用 Flask 加 SQLAlchemy 也能实现同样的功能但 Flask 的灵活性是把双刃剑项目一大人就容易写出风格混乱的代码。Django 的“全家桶”模式在这里反而是优势ORM 负责数据库操作模板系统负责页面渲染Admin 后台负责内容录入表单框架负责数据校验这些模块之间配合非常默契不需要自己去拼装。另一个关键因素是 Django 的 Admin 后台。很多非技术人员对“网站后台”的想象就是“能填表格、能传图片”Django Admin 几乎开箱即用只要定义好数据模型后台就能自动生成对应的增删改查页面。某乡镇的工作人员培训了不到半小时就学会录入内容了。这一点在真实项目中非常重要——系统做出来是要给别人用的如果后台交互太简陋最后内容根本更新不起来。Python 语言本身的优势也很明显。生态里有 Pillow 处理图片、requests 抓取接口、pandas 做数据分析后续如果想在平台上加数据可视化模块Python 这边能省不少事。村里以后要做农产品销量统计、访客流量分析直接在 Django 里写个视图返回 JSON前端用图表库渲染就行不需要再折腾一套技术栈。2.2 整体架构与数据流设计整个平台采用 Django 标准的 MVTModel-View-Template架构前后端不分离模板由 Django 在服务端渲染后返回给浏览器。有人可能会问现在不都流行前后端分离吗这个项目我特意选择了服务端渲染原因有两点一是展示型网站对交互要求不高服务端渲染首屏加载更快对手机流量用户更友好二是乡镇环境的网络带宽和服务器性能有限没必要上 Vue 或 React 那套前端打包、接口联调的复杂度只会拖慢项目进度。数据流大概是这样的管理员通过浏览器访问 Django Admin 后台录入村庄信息、图片、农产品数据这些数据经 ORM 写入数据库。访客访问网站首页或其他页面时Django 的 URL 路由根据访问地址找到对应的视图函数视图函数从数据库读取数据把数据交给模板渲染成 HTML 页面返回给浏览器。整个链路简洁清晰没有消息队列、没有缓存中间件前期阶段保持简单就是最好的设计。之后如果数据量变大可以在 Django 层加 Redis 做页面缓存也可以加一个列表页的分页机制来减轻数据库压力这些在 Django 中都有现成的方案。我在设计初期就给这些扩展留了接口比如模型里设计了“状态”字段可以控制内容是否展示避免内容编辑到一半不小心泄露出去。2.3 数据库模型设计思路这是整个项目最核心的设计环节。农村综合风貌展示涉及的数据主体有村庄基本信息、风貌分类、图集、农产品、文化活动、通知公告、轮播图配置还有后台管理需要的用户。我梳理之后将其归纳为六个核心模型第一个是村庄基本信息表用来存乡镇或村庄的文字介绍、地理坐标、面积、人口等基础数据。第二个是内容分类表用来给图片和图集打标签比如“自然风光”“人文历史”“特色产业”“村容村貌”四个大类。第三是内容表统一存放文章、图集、活动记录等具体条目通过外键关联分类。第四是图片资源表单独存储图片路径、描述、上传时间和所属条目这样一套图集可以关联多张图片。第五是农产品表保存产品名称、价格、规格、图片、介绍和联系方式。第六是轮播图表管理首页头部展示的几张焦点图片。为什么不把所有内容都塞进一张大表这个我在实际开发中踩过坑。刚开始为了省事把文章、活动、公告都放进一个内容表结果后台分类混乱写代码的时候也要各种判断内容类型。后来拆开之后代码结构瞬间清爽后台录入时也能根据不同类型展示不同的表单字段而且后期可以单独给农产品表增加库存字段、给活动表增加时间字段。ORM 的设计原则就是“按业务对象拆表”不要怕麻烦前期表和表的边界划清楚后面能省大量改代码的时间。3. 核心功能模块与关键实现3.1 数据模型的具体代码实现这里直接给出我在项目中实际用到的模型代码供大家参考。项目里我用的数据库是 MariaDB 10.5Django 版本是 4.2Python 版本是 3.10。from django.db import models from django.utils import timezone class Village(models.Model): name models.CharField(村庄名称, max_length100) intro models.TextField(村庄简介) location models.CharField(地理位置, max_length200) area models.FloatField(占地面积(平方公里)) population models.IntegerField(人口数量) created_at models.DateTimeField(创建时间, defaulttimezone.now) class Meta: verbose_name 村庄信息 verbose_name_plural verbose_name def __str__(self): return self.name class Category(models.Model): name models.CharField(分类名称, max_length100) slug models.SlugField(URL标识, uniqueTrue) class Meta: verbose_name 内容分类 def __str__(self): return self.name class Content(models.Model): title models.CharField(标题, max_length200) category models.ForeignKey(Category, on_deletemodels.PROTECT, verbose_name分类) village models.ForeignKey(Village, on_deletemodels.CASCADE, verbose_name所属村庄) body models.TextField(正文内容) cover_image models.ImageField(封面图, upload_tocovers/) is_published models.BooleanField(是否发布, defaultFalse) created_at models.DateTimeField(发布时间, auto_now_addTrue) class Meta: ordering [-created_at] verbose_name 内容条目 def __str__(self): return self.title class Image(models.Model): content models.ForeignKey(Content, on_deletemodels.CASCADE, related_nameimages, verbose_name所属内容) image models.ImageField(图片, upload_togallery/) caption models.CharField(图片说明, max_length200, blankTrue) class Meta: verbose_name 图片资源 class Product(models.Model): name models.CharField(产品名称, max_length100) village models.ForeignKey(Village, on_deletemodels.CASCADE, verbose_name产地) price models.DecimalField(价格(元/份), max_digits8, decimal_places2) description models.TextField(产品介绍) image models.ImageField(产品图, upload_toproducts/) contact models.CharField(联系电话, max_length20) class Meta: verbose_name 农产品 class Carousel(models.Model): title models.CharField(标题, max_length100) image models.ImageField(图片, upload_tocarousel/) link_url models.CharField(跳转链接, max_length300, blankTrue) sort_order models.IntegerField(排序, default0) class Meta: ordering [sort_order] verbose_name 首页轮播图这几个模型基本覆盖了平台的展示需求。注意几个细节Content 表里我加了一个 is_published 字段用来控制内容是否公开这样工作人员可以先编辑保存草稿确认无误后再勾选发布Image 表通过外键关联 Content一个内容可以对应多张图片实现了“图集”功能Product 表单独抽出来方便以后加库存管理。上架一个产品需要填价格字段我用的是 DecimalField 而不是 FloatField这个细节很多人容易忽略。浮点数在计算机里存储会有精度问题比如 1.1 在二进制里其实是一个无限循环小数但 Decimal 是字符串存储精度可控。涉及到钱的地方老老实实用 DecimalField别给自己埋坑。3.2 首页与列表页视图实现模型定义好之后视图层的工作就是把数据取出来展示给访客。以下是首页视图的核心代码from django.shortcuts import render, get_object_or_404 from django.views.generic import ListView, DetailView from .models import Carousel, Content, Village, Category, Product def home(request): carousels Carousel.objects.filter(statusTrue) villages Village.objects.all() featured_categories Category.objects.annotate(content_countmodels.Count(content)).filter(content_count__gt0)[:4] latest_contents Content.objects.filter(is_publishedTrue)[:6] products Product.objects.all()[:8] return render(request, index.html, { carousels: carousels, villages: villages, featured_categories: featured_categories, latest_contents: latest_contents, products: products, }) class ContentListView(ListView): model Content template_name content_list.html paginate_by 9 def get_queryset(self): queryset Content.objects.filter(is_publishedTrue) category_slug self.kwargs.get(slug) if category_slug: queryset queryset.filter(category__slugcategory_slug) village_id self.request.GET.get(village) if village_id: queryset queryset.filter(village_idvillage_id) return queryset首页视图里做了几件关键的事轮播图只取启用状态的分类列表统计了每个分类下有多少条内容只显示有内容的分类避免点进去空页面最新内容取 6 条农产品取 8 条作为推荐展示。这些数量是参考内容运营需求定的实际使用中可以根据数据量调整。列表页用 Django 的 ListView 通用视图省了不少重复代码。分页我设置了每页 9 条内容对应三列布局正好铺满一行。这里的 querydict 用法值得一提乡村旅游的访客通常会想只看某个特定村庄的内容所以我在列表页加了一个村庄筛选参数通过 GET 请求传递。分页配置好之后Django 会自动生成上一页下一页的导航不需要自己手写 GET 传参逻辑。3.3 详情页与图片展示方案详情页展示单条内容的完整信息。这里我建议采用 DetailView并且把图集和正文分开渲染class ContentDetailView(DetailView): model Content template_name content_detail.html slug_field title slug_url_kwarg title def get_queryset(self): return Content.objects.select_related(category, village).prefetch_related(images)def get_object(self): obj super().get_object() obj.view_count 1 obj.save(update_fields[view_count]) return obj我用select_related和prefetch_related做了查询优化。前一个方法处理外键关系的预加载一次 SQL 查询就能把内容、分类、村庄的数据都取出来后一个方法处理反向关联的图片列表避免循环查询图片明细。这两行代码在数据量小的时候看不出差别但只要内容超过几百条响应速度的差距立刻就能感知到。图片展示是我比较重视的一个环节。乡村风貌类网站访客最关心的就是图图不行其他都白搭。图片用 ImageField 存储我额外引入 Pillow 库来做尺寸压缩。上传原图到服务器之后程序会生成一个 800 像素宽的中等尺寸缩略图用于详情页展示再生成一个 400 像素宽的缩略图用于列表页。这么做的原因很实际原图一张动辄三五兆直接把原图输出到网页上手机流量用户光是加载图片就得等半天跳出率会非常高。压缩之后单张图片能压到 100-200KB视觉损失普通人完全察觉不到。3.4 农产品展示与联系模块农产品展示是这类平台带来的公共价值比较高的模块。很多村镇有优质水果、蔬菜、土特产但缺乏线上展示窗口。我在设计农产品数据表时除了基础的名称、价格、描述之外特意加了产地关联和联系电话。产地关联是为了让访客知道这个产品是哪里的、跟村庄信息呼应上联系电话则是最低成本的转化入口不需要在线支付、物流对接一个电话就能促成交易。这个模块的视频展示我后续加了支持一套产品可以绑定一个短视频地址点击后在页面内直接播放。考虑到基层的宽带环境视频我建议用现成的视频平台嵌入方式而不是直接传文件到自己的服务器上。原因稍微解释一下视频文件体积大直接放在业务服务器会造成带宽压力和存储压力而使用第三方平台的 iframe 嵌入代码十几行代码就能实现清晰度和访问速度还更有保障。4. 实操流程从环境搭建到全站跑通4.1 初始化 Django 项目与基础配置这一节我把整个项目的搭建过程完整过一遍按照这个流程操作新手也能一步一步把项目跑起来。首先创建虚拟环境。这一步很重要项目依赖的 Python 包需要隔离管理避免多个项目之间互相干扰。建议用 venv 而不是全局安装依赖python3 -m venv village_env source village_env/bin/activate然后安装核心依赖包。以稳定版为主不建议追求最新版本因为新版本可能引入不兼容的变更pip install django4.2.* pip install Pillow pip install mysqlclient接下来创建项目和核心应用。我习惯把项目命名为 config应用命名为 content这样代码结构更清晰django-admin startproject config . python manage.py startapp content创建好后需要到 settings.py 里做几项关键配置。第一是安装应用把 content 加进 INSTALLED_APPS第二是配置数据库连接第三是配置静态文件和媒体文件的存储路径。这些配置代码比较常规直接贴出来INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, content, ] DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: village_site, USER: village_user, PASSWORD: 你的数据库密码, HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, }, } } STATIC_URL /static/ STATIC_ROOT os.path.join(BASE_DIR, staticfiles) MEDIA_URL /media/ MEDIA_ROOT os.path.join(BASE_DIR, media)数据库编码一定要用 utf8mb4 而不是 utf8。utf8 在 MySQL 中只支持三个字节的编码像 emoji 表情和一些生僻汉字会存不进去而 utf8mb4 是完整的四字节 UTF-8 编码。农村风貌展示平台免不了要录入一些特殊地名用字和历史文献里的生僻字选 utf8mb4 可以省去后面数据乱码的烦恼。配置完成后执行数据库迁移命令再创建一个管理员账号python manage.py makemigrations python manage.py migrate python manage.py createsuperuser迁移做完系统的数据表结构就建好了。创建一个超级管理员后面进 Admin 后台管理内容用。4.2 Admin 后台的定制与内容录入Django 自带的后台功能很强大但默认界面比较简陋而且字段展示方式对非技术工作人员不够友好。我在 admin.py 里做了不少定制核心目的是让后台录入更直观。以下是部分关键代码from django.contrib import admin from .models import Village, Category, Content, Image, Product, Carousel class ImageInline(admin.TabularInline): model Image extra 3 admin.register(Content) class ContentAdmin(admin.ModelAdmin): list_display (title, category, village, is_published, created_at) list_filter (category, village, is_published) search_fields (title, body) list_editable (is_published,) prepopulated_fields {slug: (title,)} inlines [ImageInline] fieldsets ( (基本信息, { fields: (title, slug, category, village, cover_image) }), (正文内容, { fields: (body,), }), (发布控制, { fields: (is_published,), }), ) admin.register(Product) class ProductAdmin(admin.ModelAdmin): list_display (name, village, price, contact) list_filter (village,) search_fields (name, description)这里最有用的两个配置是list_editable和list_filter。前者允许工作人员直接在内容列表页勾选“是否发布”的复选框不用点进详情页修改批量发布时效率翻倍后者帮工作人员按分类、村庄筛选内容快速定位某类内容。分配给运营人员使用之后反馈是“比想象中好上手”。ImageInline 这个功能值得一提。它允许在录入内容页面的同一个表单里直接添加多张图片而不是录入完内容再去另一个页面传图。工作人员上传完封面图、填完正文直接在下方把图集图片一张张传好。这个流程对录入手感影响非常大内容模块的积极性也高了不少。文本编辑器方面Django Admin 默认的 Textarea 只能输入纯文本用来编辑带格式的活动介绍、历史介绍会很难受。我引入了一个简单的富文本编辑器支撑正文录入这样工作人员可以给文字加粗、加标题、插表格存到数据库里是 HTML 格式的片段详情页渲染时用模板过滤器 markdown 或 safe 输出即可。但这里有一个安全提示使用 safe 过滤器时要确保内容是可信的不能让前台访客提交的内容直接交给 safe 渲染。4.3 前端页面开发与移动端适配前台页面的开发工作主要围绕四个模板展开首页、内容列表页、内容详情页、农产品列表页。前端技术没有用到复杂的框架以原生 HTML、CSS 加少量 JavaScript 为主。CSS 框架用的是 Bootstrap因为基层技术人员可能也要自己调整布局Bootstrap 对非专业前端最友好改 class 名字就能换样式。首页采用模块化布局。顶部是导航栏包含首页、风貌展示、特色农产品、关于村庄几个入口导航栏下面是一块大图轮播区域展示村庄最美的几张照片接着是四分类入口卡片、最新内容列表、特色农产品推荐列表页面底部是联系方式和版权信息。整个布局结构清晰首屏就能把最有吸引力的图片展示出来符合内容型网站的信息层级设计原则。移动端适配是我重点强调的部分。根据后台访问统计这个平台超过六成流量来自手机微信里打开地址直接浏览。所以对 CSS 来说所有图片设置max-width: 100%保证不溢出页面导航栏在手机上折叠为汉堡菜单列表页的九宫格布局用响应式栅格类自动变成两列。上述几点做好之后手机上的阅读体验和电脑上基本没差。图片懒加载我做了处理。列表页如果有 9 张图片不加载全部图片而是优先加载浏览器可视区域其他图片等到用户往下滚动时再加载。这个优化对弱网环境提升感知非常明显实测首屏加载时间从 3 秒以上降到 1 秒以内。5. 部署上线与日常维护5.1 用 Gunicorn 加 Nginx 部署到服务器开发环境下用python manage.py runserver跑生产环境是不行的那个自带的开发服务器性能太差抗不住并发请求。生产部署我采用的标准组合是 Gunicorn 充当 Python 应用服务器Nginx 作为反向代理和静态文件服务。先安装 Gunicorn 并用它启动 Django 应用pip install gunicorn gunicorn config.wsgi:application --bind 127.0.0.1:8000 --workers 3启动参数说明workers指工作进程数经验值是 CPU 核心数乘以 2 加 1。比如一台 2 核服务器workers 设为 3 或 5 都行。不要贪多进程太多反而会因为切换开销拖慢速度。然后安装配置 Nginxserver { listen 80; server_name www.example.com; client_max_body_size 50M; location /static/ { alias /var/www/village_site/staticfiles/; } location /media/ { alias /var/www/village_site/media/; } location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }为什么要用 Nginx 转发而不是直接让 Gunicorn 监听公网端口原因有两个。第一是安全性Nginx 可以做一些基础的限流和过滤避免攻击流量直接打到 Python 进程上。第二是静态文件处理效率Django 处理一个图片请求需要走完整的 WSGI 流程而 Nginx 处理静态文件是操作系统底层的零拷贝操作速度快得多。把 Django 的精力留给动态内容整个系统的吞吐量会有质的提升。另外提醒一点Nginx 配置中我设置了client_max_body_size 50M这是为了允许工作人员在后台一次性上传比较多的图集图片。如果按默认的 1M 限制传三四张原图就会被拒绝工作人员会一头雾水排查半天才发现是 Nginx 上传限制。5.2 数据备份与定时任务配置乡村风貌展示平台虽然数据量不大但图片和内容都是基层工作人员辛苦积累的素材丢一次损失很大。我设置了每天凌晨自动备份数据库和媒体文件备份保留最近 15 天。这个任务用系统的 cron 定时任务实现0 2 * * * mysqldump -u village_user -p密码 village_site /backup/village_site_$(date \%Y\%m\%d).sql 15 2 * * * tar -czf /backup/media_$(date \%Y\%m\%d).tar.gz /var/www/village_site/media备份文件建议上传到异地存储或者另一个服务器不要跟业务数据放在同一台机器上。万一服务器磁盘坏了本地备份也会一起丢失那时候就真的一点办法都没有了。别问我是怎么知道的我经历过的最大数据事故就是服务器磁盘故障时发现备份文件也在那块坏盘上。Django 这边还可以写一个自定义管理命令来处理每周的内容汇总报告比如统计这周新增了多少条内容、哪个分类更新最频繁。这类运维和内容运营结合的小工具能让系统看起来更“正规”不过不是必需功能时间紧张可以不做。6. 常见问题与排查技巧实录6.1 图片上传后访问 404这个故障我接手时遇到最多很多新手都会踩。运行环境里python manage.py runserver时Django 会自动处理媒体文件的访问但换到生产环境用 Nginx 之后媒体文件的 URL 需要由 Nginx 来处理。如果 Nginx 配置里没有写location /media/块浏览器访问图片就会 404。排查方式很简单在浏览器地址栏直接访问一张已知存在于服务器上的图片地址看看返回的是 Nginx 的 404 还是 Django 的 404。如果是 Nginx 的 404基本确定是 Nginx 配置的问题如果显示 Django 的 404则可能是图片存储路径或文件名有问题。另一个隐蔽的坑是 MEDIA_ROOT 和 MEDIA_URL 的配置。MEDIA_ROOT是服务器上图片实际存放的目录MEDIA_URL是浏览器访问图片时的 URL 前缀。两者拼起来必须和 Nginx 的 alias 对应上。比如 MEDIA_ROOT 是/var/www/village_site/mediaNginx alias 就要指向这个目录少一层目录或者多一层目录都会 404。6.2 Admin 后台样式丢失生产环境部署后打开 Django Admin 后台发现页面完全没有 CSS 样式纯文本裸奔状态。这个问题几乎都出在python manage.py collectstatic这一步没做或者没做干净。Django 框架自带的静态文件包括 Admin 后台的 CSS、JS 文件默认是放在 Python 安装目录里的生产环境不可能直接引用 Python 包里的文件。必须执行collectstatic把全部静态文件收集到STATIC_ROOT指定的目录Nginx 才能把这些文件读出来供浏览器下载。如果执行了 collectstatic 还是没有样式检查 Nginx 有没有正确配置/static/的 alias 指向STATIC_ROOT目录。注意 alias 和 root 两个指令的行为不同alias 是替换匹配到的 URL 前缀root 是在指定目录下继续拼接完整请求路径用错会出现路径嵌套错误。6.3 MySQL 字符集乱码内容录入时中文显示正常但某些生僻字或特殊符号存进去之后前台显示成问号。这个问题的根源在数据库创建时的字符集设置。如果你创建数据库时用的是默认的 latin1 或者 utf8都会遇到这个问题。解决方法是删除数据库后用 utf8mb4 重新创建CREATE DATABASE village_site CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;同时在 Django 的 DATABASES 配置里加上OPTIONS: {charset: utf8mb4}双保险。如果数据库里已经有数据了可以执行 ALTER DATABASE 和 ALTER TABLE 语句来转换字符集但转换过程中个别数据可能损坏建议数据量不大时直接导出导入一次更稳妥。6.4 列表页分页与查询性能内容数量涨到几千条之后列表页响应速度明显变慢。排查发现是列表底部的筛选查询出的问题原因在于没有给外键字段建立索引。Django 通过 ORM 的db_index参数可以给字段加索引或者直接在外键字段上使用db_indexTruecategory models.ForeignKey(Category, on_deletemodels.PROTECT, db_indexTrue, verbose_name分类) village models.ForeignKey(Village, on_deletemodels.CASCADE, db_indexTrue, verbose_name所属村庄)加了数据库索引之后按分类和按村庄筛选的速度改善明显实测热数据查询从 1.2 秒降到了 200 毫秒以内。这里要提醒一句索引不是越多越好每个索引都会占用磁盘空间并拖慢写入速度但对展示平台这种“读多写少”的场景给外键和筛选字段建索引是绝对值得的。6.5 使用防火墙和 HTTPS部署完成后要给服务器设置防火墙只开放需要的端口。基础的做法是只放行 80HTTP、443HTTPS和 22SSH端口其他端口一律关闭。这一点在面向公网的服务器上特别重要不要图省事直接关防火墙裸奔。网站上线之后建议尽快把 HTTPS 配起来。现在主流浏览器对 HTTP 站点都标记为不安全访客看到警告后会直接关闭页面。申请 HTTPS 证书很便宜很多平台甚至提供永久免费证书配置过程网上教程也很多半天时间就能搞定。配上 HTTPS 之后网站在浏览器里的状态从“不安全”变成小锁图标观感上专业不少。结尾做这个项目最大的体会是技术层面的工作其实只占整个项目的一半另一半是理解使用者的真实需求和操作习惯。乡镇的工作人员不是专业程序员他们需要的后台不能有太复杂的概念表单要尽量直观、操作要少、流程要顺。我一开始把后台做得太“技术化”后来根据他们的反馈改了好几个版本才达到现在“培训十分钟就能上手”的状态。对于想用 Django 做内容展示类项目的朋友我建议不用一上来就追求微服务、前后端分离、容器化部署这些听起来高大上的架构。先用最朴素的方式把项目跑起来让真实用户使用再把痛点逐一优化这才是正确的路径。这个农村综合风貌展示平台项目用到的全是 Django 的基础功能但组合起来就是一套可用、可维护、可扩展的完整系统。如果你也想做类似的展示平台可以直接参考这套架构和代码思路遇到具体问题欢迎在评论区交流。
基于Django的农村综合风貌展示平台开发实战
NEXT STEP
看完公告,下一步怎么走?
把报考交给靠谱的人:材料预审、批次抢报、考前辅导、复审提醒,全程有人跟。