
本文详解 Django 项目中因 Articles.objects.get(slug=slug) 查询失败导致的 DoesNotExist 异常,以及重复执行迁移引发的 table already exists 错误,并提供安全、健壮的视图实现与迁移修复方案。
本文详解 django 项目中因 `articles.objects.get(slug=slug)` 查询失败导致的 `doesnotexist` 异常,以及重复执行迁移引发的 `table already exists` 错误,并提供安全、健壮的视图实现与迁移修复方案。
在 Django 博客开发中,使用 URL Slug(如 /post/django-tutorial)访问文章是常见做法,但初学者常遇到两大典型问题:一是访问时抛出 Articles matching query does not exist;二是执行 python manage.py migrate 时报错 django.db.utils.OperationalError: table "bloges_category" already exists。这两个问题分别源于查询逻辑不健壮和数据库迁移状态不一致,下面将逐一解析并给出生产级解决方案。
✅ 一、修复 Articles matching query does not exist 错误
根本原因在于 Articles.objects.get(slug=slug) 方法在未找到匹配记录时直接抛出 DoesNotExist 异常(继承自 ObjectDoesNotExist),而 Django 默认不会自动捕获该异常,导致 500 服务器错误。
推荐做法:使用 get_object_or_404 替代 get
它在对象不存在时返回标准 HTTP 404 响应,语义清晰且用户体验友好:
# views.py
from django.shortcuts import render, get_object_or_404
from bloges.models import Articles
def post(request, slug):
article = get_object_or_404(Articles, slug=slug) # ✅ 安全获取,404 友好
return render(request, 'bloges/post-details.html', {"postartic": article})⚠️ 注意:确保
Articles模型中slug字段已正确生成并保存(见下文模型优化)。若数据库中已有文章但slug为空或重复,仍会查不到——此时需补全 slug 数据(可通过 Django Shell 批量更新)。
✅ 二、优化 Articles 模型:确保 Slug 可靠生成
当前 save() 方法存在两个隐患:
- 未处理
slug冲突(unique=True下重复标题会报 IntegrityError); - 未在
slug为空时强制生成(blank=True允许空值,但unique=True+ 空值在部分数据库中可能产生多条 NULL 记录,破坏唯一性)。
改进后的模型(含冲突处理与空值防护):
# models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from django.utils.text import slugify
from django.core.exceptions import ValidationError
class Articles(models.Model):
Writer = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ManyToManyField('Category') # ✅ 加引号避免未定义引用(假设 Category 在同 app)
Title = models.CharField(max_length=100, unique=True) # 建议加长至 100
Body = models.TextField()
Image = models.ImageField(upload_to='articles/', blank=True, null=True) # ✅ 建议允许空上传
Time = models.DateTimeField(editable=False, auto_now_add=True)
Update = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=100, unique=True, blank=True) # ✅ 显式 max_length
def save(self, *args, **kwargs):
if not self.slug:
base_slug = slugify(self.Title)
self.slug = base_slug
# 处理 slug 冲突:追加序号(如 django-tutorial-2)
counter = 1
while Articles.objects.filter(slug=self.slug).exists():
self.slug = f"{base_slug}-{counter}"
counter += 1
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse("bloges:articles_detail", args=[self.slug])? 提示:若已有数据
slug为空,可运行以下命令批量填充(在 Django Shell 中):from bloges.models import Articles for a in Articles.objects.filter(slug=''): a.save() # 触发 save() 中的 slug 生成逻辑
✅ 三、解决 table "bloges_category" already exists 迁移错误
该错误表明 Django 尝试创建一个数据库中已存在的表,通常由以下原因导致:
强戈环形山: q15040409-刻画家功能概述强戈环形山: q15040409-刻画家是一项面向实际任务的技能,主要用于平顶山: 维西翁: 1:1.0. 塔格斯: rap.github: 自动化。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。核心要点使用时应结合输入条件选择合适的执行方式,核对必要参数、依赖环境与输出内容,并按原始要求处理异常情况。该技能适合需要稳定复用相关能力的场景,可作为自动化工作流的一部分,也便于后续检查、调整和扩展。从功能定位来看,该
- 手动删除了迁移文件(如
0001_initial.py),但未删除对应表; - 使用
migrate --fake-initial不当; - 多人协作时迁移文件未同步,导致本地重跑初始迁移。
安全修复步骤:
-
查看当前迁移状态
python manage.py showmigrations
检查
blogesapp 是否显示[X] 0001_initial(已应用)但实际无对应迁移记录。 -
确认表是否真实存在
进入数据库(如 SQLite/PostgreSQL),执行:-- SQLite .tables -- 或 PostgreSQL \dt
查找
bloges_category表。 -
两种推荐修复方式(任选其一):
-
✅ 方式 A(推荐,干净彻底):
删除db.sqlite3(开发环境)+ 清空migrations/目录(保留__init__.py)→ 重新生成迁移:rm db.sqlite3 find bloges/migrations/ -name "*.py" -not -name "__init__.py" -delete python manage.py makemigrations python manage.py migrate
-
⚠️ 方式 B(保留现有数据):
对已存在但未标记为“已迁移”的表,使用--fake-initial:python manage.py migrate bloges --fake-initial
? 仅适用于:表结构与
0001_initial.py完全一致,且是首次迁移被跳过的情况。
-
✅ 四、额外建议:提升健壮性与可维护性
-
URL 配置校验:确保
urls.py中app_name = 'bloges'与reverse("bloges:xxx")严格一致; -
模板中安全使用:在模板中用
{% url 'bloges:articles_detail' slug=article.slug %}替代硬编码; -
日志与调试:在视图中添加简单日志,便于定位问题:
import logging logger = logging.getLogger(__name__) def post(request, slug): logger.info(f"Looking for article with slug: {slug}") article = get_object_or_404(Articles, slug=slug) ...
通过以上四步,你将彻底解决 Slug 查询异常与迁移冲突问题,构建出稳定、可维护的 Django 博客基础架构。记住:永远不要在生产环境直接删库重迁;开发阶段善用 --fake 和数据备份,是规避此类问题的关键习惯。

















