Django:编辑现有对象,但保存时新建

Django: edit existing object, but new on save

在我的 Django 应用程序的博客式部分中,编辑现有条目会导致创建新条目。它应该修改现有条目。

我有一个简单的模型:

class BlogEntry(models.Model):
    ...
    slug = models.SlugField(unique=True)

以及用于编辑它的简单表格:

class BlogEntryForm(forms.ModelForm):
...
slug = forms.CharField(required=False, widget=forms.HiddenInput())

class Meta:
    model = BlogEntry
    fields = (..., 'slug')

并且视图稍微简化了,也很简单:

class BlogEditView(View):
    @method_decorator(login_required)
    def get(self, request, slug=None):
        context = {
            'user': request.user,
        }
        if slug is None:
            print('Creating new entry.')
            context['entry'] = BlogEntryForm()
            context['entry'].publication_date = datetime.datetime.now()
            return render(request, 'blog/edit.html', context)
        print('Using existing entry.')
        entry = get_object_or_404(BlogEntry, slug=slug)
        context['entry'] = BlogEntryForm(instance=entry)
        return render(request, 'blog/edit.html', context)

    @method_decorator(login_required)
    def post(self, request):
        blog_entry_form = BlogEntryForm(request.POST)
        if blog_entry_form.is_valid():
            blog_entry = blog_entry_form.save(commit=False)
            if blog_entry.slug is None or blog_entry.slug == '':
                print('New entry, slug is empty.')
                blog_entry.creation_date = datetime.datetime.now()
                blog_entry.slug = slugify(blog_entry.title) + '_' + hex(random.randint(0, 1e10))
            blog_entry.author = request.user
            blog_entry.save()
            return redirect(reverse('blog/article', args=[blog_entry.slug]))
        ...

get() 中,我通过印刷品确认我选择了正确的分支。如果该条目存在,我将使用该实例设置条目。然而,在post(),我总是走新的入口分支。

布局具有典型的隐藏元素循环。

{% for hidden in form.hidden_fields %}
    {{ hidden }} hidden
{% endfor %}

不过,可疑的是,当我查看服务时 html,我没有看到 slug 条目,所以它没有通过也就不足为奇了。

有人看到我遗漏了什么吗?

您还应该将 slug 参数添加到 post() 方法。这将允许您从数据库中获取要编辑的博客条目,并将该条目作为 instance 参数传递给表单:

@method_decorator(login_required)
def post(self, request, slug=None):
    blog_entry = BlogEntry.objects.filter(slug=slug).first()
    blog_entry_form = BlogEntryForm(request.POST, instance=blog_entry)
    ...

UPDATE:要将 slug 参数传递给 post() 方法,您应该使用 [=18] 的空 action 属性=] 标签:

<form action="" method="POST">

在这种情况下,表单将提交到加载它的 url。因此 POST 请求的 slug 参数将与 GET 相同。