如何获取Subjects模型对象ID关联Post,解决views.py的KeyError报错
问题原因
你遇到的KeyError: 'id'报错的核心原因是:PostCreateView视图尝试从URL参数中获取id,但你当前配置的post-create路由没有定义对应的<int:id>参数,因此self.kwargs中不存在id这个键。
修复步骤
1. 修改urls.py的路由配置
给帖子创建路径加上关联的主题ID参数,修改后的post创建路由如下:
urlpatterns = [ # 其他原有路由保持不变 # 注意把subject的id放在路径前面,绑定帖子对应的主题 path('<int:id>/post/new/', views.PostCreateView.as_view(), name='post-create') ]
修改后,创建帖子的路径会和对应的主题绑定,例如给ID为2的主题创建帖子的路径就是/2/post/new/。
2. 调整页面跳转链接
在主题详情页(subject-detail对应的页面)中,新增帖子的跳转链接需要传入当前主题的ID,示例模板代码:
<a href="{% url 'post-create' id=subject.id %}">给当前主题新增帖子</a>
其中subject是你SubjectDetailView传递到模板上下文中的主题对象。
3. 优化views.py的逻辑(可选但更安全)
建议先校验对应主题是否存在,避免传入非法ID报错,修改后的form_valid方法如下:
from django.shortcuts import get_object_or_404 class PostCreateView(LoginRequiredMixin, CreateView): # 注意类属性要正确缩进,否则会触发语法错误 template_name = 'post/post_create.html' model = Post fields = ['body'] success_url = '/' def form_valid(self, form): form.instance.author = self.request.user # 先校验主题是否存在,不存在直接返回404 subject = get_object_or_404(Subjects, id=self.kwargs['id']) form.instance.subject = subject # 不需要手动调用form.save(),父类方法会自动保存 return super(PostCreateView, self).form_valid(form)
额外优化建议
你Post模型中subject字段的related_name设为了subject_model,而你在Subjects模型中单独写了posts属性查询关联帖子,其实可以直接把related_name改为posts,即可删除自定义的posts属性,通过subject.posts.all()直接查询对应主题下的所有帖子,代码更简洁:
class Post(models.Model): subject = models.ForeignKey( Subjects, on_delete=models.CASCADE, related_name='posts') # 其余字段保持不变
内容的提问来源于stack exchange,提问作者Jack Junior
相关产品推荐
相关产品推荐

