【问题标题】:"Cannot force an update in save() with no primary key"- when submitting an edit/update form“无法在没有主键的情况下强制更新 save()”- 提交编辑/更新表单时
【发布时间】:2026-01-16 10:40:01
【问题描述】:

我有一个编辑表单,我只想更新帖子的“标题”、“内容”和“类别”。为此,我在保存表单时包含了update_fields。但是,这有一个小问题。当我提交表单时,Django 会引发 ValueError(特别是“无法在没有主键的情况下强制更新 save()”)。为什么会这样,我该如何解决?

发帖形式:

class PostForm(forms.ModelForm):

    def __init__(self,  *args, **kwargs):
        super().__init__(*args, **kwargs)
        for key in ['postTitle', 'postContent', 'category']:
            self.fields[key].widget.attrs.update({'class': 'form-control'})         
        self.fields['content'].widget.attrs.update(width='100px', height='50')

    class Meta:
        model = Post
        fields = ('title', 'content', 'category') 

后模型:

class Post(models.Model):
    title = models.CharField(max_length = 100)
    URL = models.SlugField() # slug for url 
    content = models.TextField()
    author = models.ForeignKey(User, on_delete = models.CASCADE, related_name = 'posts') # id of author
    category = models.CharField(max_length = 9, default = 'General') # category the post is in
    creationDate = models.DateTimeField()

编辑视图:

def editPost(request, pk):
    if request.method == 'GET':
        post = get_object_or_404(Post, pk = pk)
        if post.author == request.user:
            form = PostForm(instance = post)
            return render(request, 'editPost.html',  {'form': form, 'post': post})
        else:
            return redirect('viewPost', pk = pk, postURL = post.postURL)
    if request.method == 'POST':
        post = get_object_or_404(Post, pk = pk)
        form = PostForm(request.POST)
        if post.author == request.user:
            if form.is_valid():
                post = form.save(commit=False)
                post.URL = slugify(post.postTitle)
                post.save(update_fields = ['title', 'content', 'category', 'postURL'])
    return redirect('viewAll')

【问题讨论】:

  • 我之前没有使用过表单,但是您能确认是哪一行导致了这里的异常吗?是否可以在 post = form.save(commit=False) 行提出?
  • 它是在 form.save() 的最后一行提出的

标签: django


【解决方案1】:

您似乎要在此处重新分配帖子。在这一行;

post = get_object_or_404(Post, pk = pk)

您正在从数据库中获取 Post 实例。然后在这一行;

post = form.save(commit=False)

您正在将 post 变量重新分配给未保存的 Post 实例,其中仅填充了 request.POST 中可用的数据。然后,当您想使用 update_fields 参数保存这篇文章时:

post.save(update_fields = ['title', 'content', 'category', 'postURL'])

ValueError 被引发是因为您尝试保存的 Post 实例没有 id,它只有 request.POST

中可用的内容

【讨论】:

  • 这是我的怀疑。
  • 好的 - 我把它从 form = PostForm(request.POST) 改成了 form = PostForm(request.POST, instance = post)`。现在是另一个愚蠢的问题,因为我在安全方面非常糟糕 - 更改这条线会打开任何我可能不知道的安全漏洞吗?
  • @vjwvebjkwev 我不确定,以前没有使用过表单,但是如果我向 /posts/5 发送发布请求,代码会如何表现(假设我是id 为 5) 的帖子,但在请求 POST 数据中提供另一个 id?我可以更改另一个帖子的作者字段作为我的用户吗?一般来说,这看起来不是使用 django 表单更新模型实例的最佳做法。
  • 好收获! (这就是为什么我说我在安全性方面不是最好的......:p)我添加了一行代码来检查当前用户的表单实例(使用 request.POST)以及检查主要帖子变量。
最近更新 更多