# 广东外语外贸大学南国商学院-pythonweb大作业 > 参考IP:[47.103.207.39](http://47.103.207.39) > > python版本3.7.x > > [项目代码仓库](https://git.anyi.space/gwng/gwng-pythonweb) > > 参考网站:[计算机学院官网](https://www-new.gwng.edu.cn/xkxy/main.psp) > > 参考教程 > > | 名称 | 地址 | > | --------- | -------------------------------------------------------- | > | Django | https://www.runoob.com/django/django-tutorial.html | > | Bootstrap | https://www.runoob.com/bootstrap/bootstrap-tutorial.html | > > 使用python库依赖 > > | 名称 | 备注 | > | -------- | ------------- | > | Django | web 模板引擎 | > | markdown | markdown2html | > > ## 初始化 使用python 3.7.6 1. 安装Django `pip install Django` 2. 创建初始化项目 `django-admin startproject pythonweb` 3. 运行测试 `python manage.py runserver 0.0.0.0:8000` 4. 新增模块 `python manage.py startapp homeApp` 5. 配置新增模块 ```python INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'homeApp',#主页 'aboutApp',#学院简介 'teamApp',#教师团队 'scientificApp',#科研 'partyApp',#党建 'admissionsAndEmploymentApp',#招生和就业 ] ``` 6. 创建依赖管理文件 `pip freeze > requirements.txt` 7. 创建static静态资源目录和templates模板目录 >编辑settings.py文件,配置静态资源加入django管理 > >`` > >配置模板的路径 > >```python >TEMPLATES = [ > { > ..., > 'DIRS': [BASE_DIR / 'templates'], > }, >] >``` > >配置静态资源 > >```python >STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),) >``` > > 8. 路由配置 - 正向路由配置,编辑urls.py文件 ```python from django.contrib import admin from django.urls import path from homeApp.views import home urlpatterns = [ path('admin/', admin.site.urls), path('',home,name='home'), #正向路由 ] ``` - 反向路由,编辑urls.py ```python from django.conf.urls import include urlpatterns = [ ..., path('aboutApp/', include('aboutApp.urls')), ] ``` > 在aboutApp中添加一个urls.py文件,并进行路由配置 > > ```python > from django.urls import path > from . import views > > app_name = 'aboutApp' > > urlpatterns = [ > path('survey/', views.survey, name='survey'), # 学院概况 > path('leader/', views.leader, name='leader'), # 领导分工 > ] > ``` 9. 数据模型配置 - 创建一个common模块,在models.py中定义数据模型 > 定义一个文章模型和轮播图模型 ```python class Article(models.Model): CATEGORY_CHOICES = [ ('professional', '专业介绍'), ('leader', '领导分工'), ('academic_leader', '学院学科建设带头人教师'), ('computer_science', '计算机系教师'), ('software_engineering', '软件工程系教师'), ('digital_media', '数字媒体技术系教师'), ('iot_networking', '物联网与网络工程系教师'), ('math_teaching', '数学教研室教师'), ('party_work', '党政学工队伍教师'), ('scientific', '教学科研'), ('party_dynamic', '党建动态'), ('youth_dynamic', '团学动态'), ('admissions', '招生'), ('employment', '就业'), ] title = models.CharField(max_length=200, verbose_name='标题') markdown_content = models.TextField(verbose_name='markdown内容') #blank=True配置字段非必填 html_content = models.TextField(verbose_name='html内容',blank=True) created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') category = models.CharField(max_length=50, choices=CATEGORY_CHOICES, verbose_name='文章分类') cover = models.URLField(verbose_name='封面') class Meta: ordering = ['-created_at'] def __str__(self): return self.title class Banner(models.Model): title = models.CharField(max_length=200, verbose_name='标题') url = models.URLField(verbose_name='链接') order = models.IntegerField(default=0, verbose_name='序号') class Meta: ordering = ['order'] def __str__(self): return self.title ``` - 在admin中注册定义的模型,编译admin.py文件 ```python from django.contrib import admin from common.models import Article, Banner # Register your models here. admin.site.register(Article) admin.site.register(Banner) ``` > 更新模型信息:`python manage.py makemigrations common` > > 同步模型与数据表`python manage.py migrate common` > > 创建超级管理员用于登陆django的后台:`python manage.py createsuperuser ` ## 工作内容分工 - 图片链接收集 - 文章数据收集(html2markdown) - 前端页面开发 - 管理后台开发 - 前后端对接 - 功能测试与接口测试 - 初始数据维护 - 打包部署上线 | 姓名 | 负责内容 | 备注 | | ------ | -------------------- | ---- | | 黄略 | 总体设计、前后端开发 | | | 杨昊廷 | 前后端开发 | | | 李锐 | 数据采集、数据清洗 | | | 朱启政 | 数据采集、数据清洗 | | | 毕熙 | 数据录入、数据维护 | | ## 功能模块 > 参考网站:[计算机学院官网](https://www-new.gwng.edu.cn/xkxy/main.psp) - 首页 - 学院信息 - 学院概况 - 领导分工 - 机构设置 - 专业介绍 - 教师队伍 - 学院学科建设带头人 - 计算机系 - 软件工程系 - 数字媒体技术系 - 物联网与网络工程系 - 数学教研室 - 党政学工队伍 - 科研工作 - 党团工作 - 党建工作 - 团学工作 - 招生就业 - 招生信息 - 就业信息 ## 数据库设计 #### 概要设计 - 文章(**ID**,标题,markdown内容,,html内容,时间,创建人,文章分类,封面) > 文章分类:专业介绍,领导分工,学院学科建设带头人教师,计算机系教师,软件工程系教师,数字媒体技术系教师,物联网与网络工程系教师,数学教研室教师,党政学工队伍教师,教学科研,党建动态,团学动态,招生,就业 - 首页轮播图(标题,链接,序号) #### 物理设计 项目设计了两个核心模型,均定义在 `common` 模块中: **Article(文章模型):** 存储所有模块的文章内容,通过 `category` 字段区分所属模块。内容以 Markdown 格式存储,请求时渲染为 HTML。 | 字段 | 类型 | 说明 | | ---------------- | ------------- | --------------------- | | title | CharField | 文章标题 | | markdown_content | TextField | Markdown 格式内容 | | html_content | TextField | HTML 格式内容(预留) | | category | CharField | 文章分类(14 种) | | cover | URLField | 封面图片链接 | | created_at | DateTimeField | 创建时间 | | updated_at | DateTimeField | 更新时间 | **Banner(轮播图模型):** 存储首页轮播图数据。 | 字段 | 类型 | 说明 | | ----- | ------------ | -------- | | title | CharField | 标题 | | url | URLField | 图片链接 | | order | IntegerField | 排序序号 | **数据库ER图:** ```mermaid erDiagram Article { int id PK string title text markdown_content text html_content datetime created_at datetime updated_at string category string cover } Banner { int id PK string title string url int order } ``` ### ## 构建部署 ### 构建docker镜像及运行 - dockerfile文件 ```dockerfile # 使用官方Python 3.9镜像作为基础 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 设置环境变量 ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ DJANGO_SETTINGS_MODULE=pythonweb.settings # 安装Python依赖 RUN pip install --no-cache-dir Django Markdown # 复制项目文件 COPY ./pythonweb . # 创建非root用户 RUN useradd -m -u 1000 django && chown -R django:django /app USER django # 暴露端口 EXPOSE 8000 # 启动命令 CMD ["python", "/app/pythonweb/manage.py", "runserver", "8000"] ``` 使用`docker build ./ -t gwng-pythonweb:v1.0`命令构建docker镜像 使用`docker run --name gwng -p 8000:8000 gwng-pythonweb:v1.0`命令运行 ### 申请域名SSL证书 ```shell #安装certbot apt install cerbot #使用certbot向letsencrypt申请SSL证书 certbot certonly --webroot -w /home/nginx/www/ -d pythonweb.display.anyi.space ``` ### 使用nginx反向代理 ```nginx upstream pythonwebServer{ server 127.0.0.1:8000; } server{ listen 80; listen [::]:80; server_name pythonweb.display.anyi.space; client_max_body_size 1024m; #certbot自动续签使用的验证路径映射 location ^~ /.well-known/acme-challenge/ { root /home/nginx/www/; } location / { proxy_pass http://pythonwebServer; proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } server{ listen 443 ssl; server_name pythonweb.display.anyi.space; ssl_certificate /etc/letsencrypt/live/pythonweb.display.anyi.space/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/pythonweb.display.anyi.space/privkey.pem; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; location / { proxy_pass http://pythonwebServer; proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ```