在Django Admin中无法隐藏slug字段?排除slug字段触发KeyError的原因咨询
解决Django Admin中排除slug字段触发KeyError的问题
你遇到的这个KeyError本质是Admin配置里的两个设置冲突了:你同时用exclude=('slug',)把slug字段从表单中移除,又设置了prepopulated_fields = {'slug': ('title',)}让Admin自动填充slug字段。
为什么会冲突?
prepopulated_fields的作用是告诉Django Admin:在表单里给slug字段生成一个自动填充的输入框,它依赖于表单中必须存在slug字段。- 但
exclude会把slug字段从Admin表单里彻底移除,这就导致Django Admin试图找到slug字段来设置自动填充逻辑时,找不到对应的字段,于是抛出了KeyError。
两种解决思路
根据你的需求选择对应的方案:
方案1:完全隐藏slug字段(无需手动填充)
如果你希望slug字段完全不在Admin表单中显示,而是通过代码自动生成(比如在模型保存时自动生成),那么:
- 删除
prepopulated_fields = {'slug': ('title',)}这一行配置 - 保留
exclude=('created_at','slug',) - 记得在模型的
save方法中添加自动生成slug的逻辑(避免slug字段为空报错):
修改后的models.py:
from django.db import models from django.utils import timezone from django.urls import reverse from django.utils.text import slugify # 导入slugify class Post(models.Model): title= models.CharField(max_length=50,null=False,blank=False) content= models.TextField(max_length=2000,null=False,blank=False) image= models.ImageField( upload_to="post-img/") created_at=models.DateTimeField(default=timezone.now) author=models.CharField(max_length=50,null=True,blank=True) slug=models.SlugField(max_length=30) class Meta: verbose_name =("Post") verbose_name_plural =("Posts") def __str__(self): return self.title def get_absolute_url(self): return reverse("PostDetail", kwargs={'slug': self.slug}) def headline(self): return self.content[:50]+'...' # 添加自动生成slug的逻辑 def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.title) super().save(*args, **kwargs)
修改后的admin.py:
from django.contrib import admin from .models import Post class PostAdmin(admin.ModelAdmin): exclude=('created_at','slug',) list_display=['title','headline','author','created_at'] admin.site.register(Post,PostAdmin)
方案2:保留自动填充,但让slug字段只读
如果你还是想让Admin自动从title生成slug,但不想让用户编辑这个字段,那么:
- 不要用
exclude移除slug字段 - 添加
readonly_fields=('slug',)让字段只读 - 保留
prepopulated_fields配置
修改后的admin.py:
from django.contrib import admin from .models import Post class PostAdmin(admin.ModelAdmin): exclude=('created_at',) readonly_fields=('slug',) # 设置slug为只读 list_display=['title','headline','author','created_at','slug'] # 可选:在列表页显示slug prepopulated_fields = {'slug': ('title',)} admin.site.register(Post,PostAdmin)
内容的提问来源于stack exchange,提问作者El Houssain Sabri
相关产品推荐
相关产品推荐

