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

如何在Django中从Markdown文件填充SQLite数据库?

Django 从Markdown文件自动填充SQLite数据库方案

一、CSV替代与Django专属工具

  • 完全可以用JSON替代CSV,但对你的场景来说,直接解析Markdown自带的YAML头部更高效,无需转格式。Django有loaddata命令可导入JSON/YAML格式的 fixture,但针对从Markdown批量提取内容的需求,自定义管理命令是更灵活的标准实现方式。

二、解析Markdown并导入的简单示例

1. 定义文章模型(models.py)

from django.db import models
from django.utils.text import slugify

class Article(models.Model):
    title = models.CharField(max_length=200)
    pub_date = models.DateField()
    slug = models.SlugField(unique=True)
    content = models.TextField()
    tags = models.CharField(max_length=200, blank=True)  # 简单标签存储,也可使用django-taggit扩展
    cover_image = models.CharField(max_length=255, blank=True)  # 存图片路径而非BLOB

    def __str__(self):
        return self.title

2. 编写自定义导入命令

在你的app目录下创建management/commands/import_articles.py:

import os
import yaml
import markdown
from django.core.management.base import BaseCommand
from django.utils.text import slugify
from your_app_name.models import Article  # 替换为你的app名称

class Command(BaseCommand):
    help = '批量导入articles目录下的Markdown文章到数据库'

    def handle(self, *args, **options):
        base_dir = 'articles'
        # 遍历YYYY/MM的目录结构
        for year_dir in os.listdir(base_dir):
            if not year_dir.isdigit():
                continue
            year_path = os.path.join(base_dir, year_dir)
            for month_dir in os.listdir(year_path):
                if not month_dir.isdigit():
                    continue
                month_path = os.path.join(year_path, month_dir)
                for filename in os.listdir(month_path):
                    if not filename.endswith('.md'):
                        continue
                    file_path = os.path.join(month_path, filename)
                    with open(file_path, 'r', encoding='utf-8') as f:
                        raw_content = f.read()
                        # 分离YAML头部和Markdown正文
                        if raw_content.startswith('---'):
                            yaml_part, md_part = raw_content.split('---', 2)[1:]
                            meta_data = yaml.safe_load(yaml_part.strip())
                            md_content = markdown.markdown(md_part.strip())

                            # 生成slug,优先用YAML里的标题,否则用文件名
                            article_slug = slugify(meta_data.get('title', os.path.splitext(filename)[0]))
                            # 创建或更新文章(避免重复导入)
                            article, created = Article.objects.get_or_create(
                                slug=article_slug,
                                defaults={
                                    'title': meta_data['title'],
                                    'pub_date': meta_data['date'],
                                    'content': md_content,
                                    'tags': meta_data.get('tags', ''),
                                    'cover_image': meta_data.get('cover_image', '')
                                }
                            )
                            if created:
                                self.stdout.write(self.style.SUCCESS(f'成功导入文章: {article.title}'))
                            else:
                                self.stdout.write(self.style.WARNING(f'文章已存在,跳过: {article.title}'))

3. 执行导入命令

python manage.py import_articles

三、图片/视频存储建议

绝对不要用BLOB格式存储,原因如下:

  • 会导致数据库体积暴涨,大幅降低读写性能
  • 无法直接通过HTTP访问,需额外编写视图处理资源请求
  • 不符合静态资源的常规管理流程

正确做法:

  • 将图片、视频放在Django的media或static目录下
  • 在Markdown的YAML头部或正文中记录资源的相对路径(如/media/articles/2024/05/cover.jpg)
  • 在模板中通过{% static %}或{% media %}标签渲染资源链接

四、Jinja2配置方法

若要替换Django默认模板引擎为Jinja2,在settings.py中修改TEMPLATES配置:

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [os.path.join(BASE_DIR, 'jinja2_templates')],  # 自定义Jinja2模板目录
        'APP_DIRS': True,
        'OPTIONS': {
            'trim_blocks': True,
            'lstrip_blocks': True,
        },
    },
    # 可选保留Django模板引擎,兼容admin等内置功能
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 14:47:39