:::tip 文章管理 文章管理模块支持富文本编辑、分类关联、封面图片上传、图集管理等功能。适用于新闻、公告、帮助文档等内容管理场景。 ::: ## 模块结构 ``` application/article/ ├── models.py # 文章模型 ├── forms.py # 表单验证 ├── services.py # 业务逻辑层(自定义函数) ├── views.py # 视图层 └── urls.py # 路由配置 ``` :::warning 自定义 Service 文章模块因涉及文件处理、富文本清洗、图集解析等复杂逻辑,编写自定义 service 函数而非继承通用模式。 ::: ## 文章模型 ```python # application/article/models.py from application.models import BaseModel class Article(BaseModel): """文章模型类""" class Meta: db_table = 'django_article' category_id = models.IntegerField(null=True, blank=True, verbose_name='分类ID') title = models.CharField(max_length=150, null=True, blank=True, verbose_name='文章标题') cover = models.CharField(max_length=255, null=True, blank=True, verbose_name='文章封面') images = models.TextField(null=True, blank=True, verbose_name='文章图集') intro = models.CharField(max_length=255, null=True, blank=True, verbose_name='文章导读') content = models.TextField(null=True, blank=True, verbose_name='文章内容') author = models.CharField(max_length=100, null=True, blank=True, verbose_name='文章作者') status = models.IntegerField(default=0, verbose_name='文章状态:0-正常 1-下架') click = models.IntegerField(default=0, verbose_name='文章点击率') sort = models.IntegerField(default=0, verbose_name='文章排序') ``` ### 字段说明 | 字段 | 类型 | 说明 | |------|------|------| | `category_id` | int | 所属分类 ID(关联 category 表) | | `title` | str | 文章标题 | | `cover` | str | 封面图片路径 | | `images` | str | 图集路径(逗号分隔) | | `intro` | str | 文章导读/摘要 | | `content` | str | 富文本内容(HTML) | | `author` | str | 文章作者 | | `status` | int | 状态:0-正常 1-下架 | | `click` | int | 点击次数(自动统计) | | `sort` | int | 排序权重 | ## 文章状态流转 ``` 草稿(0) → 发布(0) → 下架(1) → 重新发布(0) ``` | 状态 | 说明 | 可执行操作 | |------|------|-----------| | 0-正常 | 文章已发布,前台可见 | 编辑、下架、删除 | | 1-下架 | 文章已下架,前台不可见 | 编辑、重新发布、删除 | ## 文件处理机制 文章模块涉及三类文件字段,处理方式各不相同: ### 1. 封面图片(cover)-- save_file ```python # 新增时 cover = save_file(data.cover, "article") if data.cover else None ``` `save_file(url, directory)` 的处理逻辑: 1. 将前端传来的 URL 还原为磁盘绝对路径 2. 若文件在临时目录(`temp/`),移动到正式目录(`upload/article/日期/`) 3. 返回相对路径存入数据库 ### 2. 图集(images)-- _build_images / _parse_images 图集在数据库中存储为逗号分隔的相对路径字符串: ``` /article/20260907/a.png,/article/20260907/b.png ``` 前端传入数组,后端拼接为字符串存储: ```python def _build_images(images_list): """将图片列表拼接为逗号分隔的字符串""" if not images_list: return None return ",".join([save_file(img, "article") for img in images_list]) def _parse_images(images_str): """将逗号分隔的字符串解析为完整 URL 列表""" if not images_str: return [] return [get_file_url(img) for img in images_str.split(",")] ``` ### 3. 富文本内容(content)-- save_content ``` 原始 HTML → 提取图片 → 迁移文件 → 替换路径 → 设置 alt → 存库 ``` ```python from utils.common import save_content # 处理富文本内容 content = save_content(content, title, "article") ``` ## 添加文章 ```python def add_article(request): """添加文章""" data, error = parse_request_body(request) if error: return R.failed(msg=error) # 表单验证 form = forms.ArticleForm(data) if not form.is_valid(): return R.failed(msg=regular.get_err(form)) try: cleaned_data = form.cleaned_data # 处理封面图片 cover = save_file(cleaned_data.get('cover'), "article") if cleaned_data.get('cover') else None # 处理图集 images = _build_images(cleaned_data.get('images')) # 处理富文本内容 content = save_content(cleaned_data.get('content'), cleaned_data.get('title'), "article") # 创建文章 Article.objects.create( category_id=cleaned_data.get('categoryId'), title=cleaned_data.get('title'), cover=cover, images=images, intro=cleaned_data.get('intro'), content=content, author=cleaned_data.get('author'), status=cleaned_data.get('status', 0), sort=cleaned_data.get('sort', 0), create_user=get_username(request), update_user=get_username(request) ) return R.ok(msg="创建成功") except Exception as e: logging.error(f"添加文章异常: {str(e)}") return R.failed(msg="添加失败,请稍后重试") ``` ## 查询分页 ### 过滤条件 | 参数 | 类型 | 说明 | |------|------|------| | `title` | 模糊搜索 | 文章标题 | | `category_id` | 精确匹配 | 分类 ID | | `status` | 精确匹配 | 文章状态 | ### 排序规则 按 `sort` 降序 -> `id` 降序。 ### 响应数据 ```json { "id": 1, "title": "DjangoAdmin 3.0 发布", "cover": "http://domain/uploads/article/20260908/cover.png", "images": ["http://domain/uploads/article/20260908/1.png"], "intro": "DjangoAdmin 3.0 正式发布...", "content": "
文章内容...
", "author": "admin", "status": 0, "statusText": "正常", "click": 100, "sort": 1, "categoryId": 1, "categoryName": "产品动态", "createUser": "admin", "createTime": "2026-09-08 10:00:00" } ``` ## API 接口 | 接口 | 方法 | 权限节点 | 说明 | |------|------|---------|------| | `/article/page` | GET | `sys:article:page` | 分页查询 | | `/article/detail/