You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向Django应用上传新网页并实现静态项目访问功能

实现方案

1. 基础配置调整

首先明确Django的目录分工:templates目录仅用于存放需要Django模板引擎渲染的模板文件,独立JS项目的静态资源属于可公开访问的内容,应该通过Django的媒体文件体系处理,不要和站点本身的静态资源、模板文件混存,这也是你之前放在templates目录下资源加载失败的核心原因。
首先修改settings.py配置:

# 其他配置保持不变
MEDIA_URL = '/media/'
# 上传的所有项目都会存在这个目录下
MEDIA_ROOT = BASE_DIR / 'media'

然后在项目根目录的urls.py中添加媒体文件访问路由(开发环境生效,生产环境建议用Nginx直接代理):

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # 你原有路由保持不变
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

2. 设计项目存储模型

在你对应应用的models.py中新增项目存储模型,支持上传zip压缩包(后台无法直接上传文件夹,要求上传前将项目所有文件打包为zip即可):

from django.db import models
from django.utils.text import slugify
import zipfile
import os
from django.conf import settings

class JSProject(models.Model):
    name = models.CharField("项目名称", max_length=100)
    slug = models.SlugField("访问路径标识", unique=True, blank=True)
    project_zip = models.FileField("项目压缩包", upload_to="project_zips/")
    extract_path = models.CharField("解压后路径", max_length=200, blank=True)

    def save(self, *args, **kwargs):
        # 自动生成slug
        if not self.slug:
            self.slug = slugify(self.name)
        super().save(*args, **kwargs)
        # 上传后自动解压
        if self.project_zip and not self.extract_path:
            extract_dir = os.path.join(settings.MEDIA_ROOT, 'js_projects', self.slug)
            os.makedirs(extract_dir, exist_ok=True)
            # 解压zip
            with zipfile.ZipFile(self.project_zip.path, 'r') as zip_ref:
                # 安全校验:过滤路径穿越和非允许后缀的文件
                allowed_suffixes = {'.html', '.css', '.js', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.woff', '.woff2', '.ttf'}
                for file in zip_ref.namelist():
                    # 禁止路径穿越
                    if '..' in file or file.startswith('/'):
                        continue
                    # 校验后缀
                    if os.path.splitext(file)[1].lower() not in allowed_suffixes:
                        continue
                    zip_ref.extract(file, extract_dir)
            self.extract_path = f'js_projects/{self.slug}'
            super().save(update_fields=['extract_path'])

    def __str__(self):
        return self.name

写完模型后执行python manage.py makemigrations和python manage.py migrate生成数据库表,再把这个模型注册到admin.py里就可以在后台上传项目了。

3. 配置访问路由和视图

首先新增视图函数,处理项目访问请求:

from django.http import HttpResponse, Http404
from django.conf import settings
import os
import mimetypes
from .models import JSProject

def serve_js_project(request, project_slug, file_path=''):
    # 先找到对应项目
    try:
        project = JSProject.objects.get(slug=project_slug)
    except JSProject.DoesNotExist:
        raise Http404("项目不存在")
    # 没有指定文件时默认返回index.html
    if not file_path:
        file_path = 'index.html'
    # 拼接完整文件路径
    full_file_path = os.path.join(settings.MEDIA_ROOT, project.extract_path, file_path)
    # 校验文件是否存在、是否在允许的目录内(防止路径穿越)
    if not os.path.exists(full_file_path) or not full_file_path.startswith(os.path.join(settings.MEDIA_ROOT, project.extract_path)):
        raise Http404("资源不存在")
    # 读取文件并返回,设置正确的MIME类型
    with open(full_file_path, 'rb') as f:
        content = f.read()
    content_type, _ = mimetypes.guess_type(full_file_path)
    return HttpResponse(content, content_type=content_type)

然后在urls.py中添加对应路由:

urlpatterns = [
    # 原有路由保持不变
    path('projects/<slug:project_slug>/', serve_js_project, name='js_project_root'),
    path('projects/<slug:project_slug>/<path:file_path>', serve_js_project, name='js_project_file'),
]

注意事项

  • 生产环境请配置Nginx直接代理/media/js_projects/路径,不需要经过Django处理,性能和安全性更高
  • 可以根据需要调整模型中的允许文件后缀,避免上传恶意可执行文件
  • 上传的zip包根目录需要直接包含index.html,不要嵌套多层文件夹,否则访问时会找不到入口文件
  • 如果需要手动迁移原有项目,直接将项目文件夹放入media/js_projects/下对应slug的目录即可,不需要上传zip包

内容的提问来源于stack exchange,提问作者Micheal Nestor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 12:09:00