如何在Django网站中展示GitHub仓库的README.md文件内容
Django站点展示GitHub仓库README实现方案
整体逻辑分为三步:拉取指定仓库的README原始Markdown内容、将Markdown转为安全的HTML内容、在Django模板中渲染展示。
依赖安装
需要三个第三方库:
requests:发起HTTP请求拉取README内容markdown:将Markdown文本转换为HTMLbleach:过滤转换后HTML中的危险标签,避免XSS安全问题
执行安装命令:pip install requests markdown bleach
核心代码实现
1. 视图函数编写
视图负责参数校验、内容拉取、格式转换、安全过滤,示例代码如下:
import requests import markdown import bleach from django.http import Http404 from django.template import loader from django.core.cache import cache # 配置HTML标签白名单,仅放行排版需要的安全标签 ALLOWED_TAGS = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'ul', 'ol', 'li', 'pre', 'code', 'blockquote', 'a', 'img', 'strong', 'em', 'hr', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'br' ] # 配置标签允许的属性 ALLOWED_ATTRIBUTES = { 'a': ['href', 'title'], 'img': ['src', 'alt', 'title'] } def repo_readme(request, owner, repo): # 校验传入的所有者、仓库名参数合法性,拦截特殊字符 valid_char = lambda s: s.replace('-', '').replace('_', '').replace('.', '').isalnum() if not valid_char(owner) or not valid_char(repo): raise Http404("仓库参数不合法") # 优先读缓存,避免频繁请求GitHub触发限流 cache_key = f"repo_readme_{owner}_{repo}" safe_html = cache.get(cache_key) if not safe_html: readme_raw = None # 依次尝试main、master两个最常见的默认分支拉取README for branch in ['main', 'master']: try: resp = requests.get( f"https://raw.githubusercontent.com/{owner}/{repo}/{branch}/README.md", timeout=5, headers={"User-Agent": "Mozilla/5.0 (compatible; ReadmePreviewBot/1.0)"} ) if resp.status_code == 200: readme_raw = resp.text break except requests.exceptions.RequestException: continue if not readme_raw: raise Http404("未找到对应仓库的README文件") # Markdown转HTML,开启代码块、表格扩展 html_content = markdown.markdown( readme_raw, extensions=['fenced_code', 'tables', 'codehilite'] ) # 过滤危险标签与属性 safe_html = bleach.clean( html_content, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRIBUTES, strip=True ) # 写入缓存,有效期30分钟 cache.set(cache_key, safe_html, 60*30) # 传入模板渲染 template = loader.get_template('readme_view.html') context = { 'owner': owner, 'repo': repo, 'readme_content': safe_html } return template.render(context, request)
2. 路由配置
在应用的urls.py中添加路由映射,支持通过URL传入所有者和仓库名参数:
from django.urls import path from . import views urlpatterns = [ path('repo/<str:owner>/<str:repo>/readme/', views.repo_readme, name='repo_readme'), ]
3. 模板编写
在templates目录下新建readme_view.html,渲染过滤后的README内容,可自定义样式匹配站点风格:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>{{ owner }}/{{ repo }} 项目说明</title> <style> .readme-wrap { max-width: 920px; margin: 2rem auto; padding: 0 1rem; line-height: 1.6; } pre { background: #f6f8fa; padding: 1rem; border-radius: 6px; overflow-x: auto; } code { background: #f6f8fa; padding: 0.2rem 0.4rem; border-radius: 3px; font-family: Consolas, Monaco, monospace; } pre code { padding: 0; background: transparent; } blockquote { border-left: 4px solid #dfe2e5; padding-left: 1rem; color: #6a737d; margin: 1rem 0; } table { border-collapse: collapse; width: 100%; margin: 1rem 0; } th, td { border: 1px solid #dfe2e5; padding: 0.5rem 1rem; } img { max-width: 100%; } </style> </head> <body> <div class="readme-wrap"> <h1>{{ owner }} / {{ repo }}</h1> <hr> {{ readme_content|safe }} </div> </body> </html>
注意事项
- 缓存必须配置:GitHub公开接口有请求频率限制,加缓存既能降低被限流的概率,也能提升页面加载速度,缓存时长可根据自己的需求调整。
- 私有仓库适配:如果需要展示私有仓库的README,在requests请求头中添加
Authorization字段,传入GitHub个人访问令牌即可,令牌不要硬编码在代码中,建议存放在环境变量或Django私密配置里。 - 分支兼容:如果需要覆盖非main/master默认分支的场景,可以先请求仓库元信息获取默认分支名,再拼接README拉取地址,常规场景下两个分支兜底足够使用。
- 安全过滤不可省略:直接渲染未经过滤的Markdown转义结果会存在XSS风险,必须通过白名单方式过滤危险标签和属性。
内容的提问来源于stack exchange,提问作者Tom Cohen
相关产品推荐
相关产品推荐

