Django表单创建新实例而不是更新现有实例

时间:2016-09-08 20:21:00

标签: python django

我已经看到这个问题在这里问了很多时间,但我无法弄清楚为什么它在我的案例中不起作用。 我有以下视图代码:

def edit(request, coffee_id=None):
coffee = get_object_or_404(Drink, pk=coffee_id) if coffee_id else Drink()
if request.method == 'POST':
    form = CoffeeForm(request.POST, instance=coffee)
    if form.is_valid():
        form.save()
        return HttpResponseRedirect(urlresolvers.reverse('coffee:index'))
else:
    form = CoffeeForm(instance=coffee)

return render(request, 'edit.html', {'coffee_form': form})

如果在数据库中存在参数中给出的coffee_id,则应该创建一个新的咖啡实例或更新一个新实例。

然而,即使数据库中存在coffee_id,也始终会创建一个新的咖啡实例。

我还尝试保存咖啡实例而不保存表单,但它也是如此。

有什么东西我做错了吗?我应该在模型中设置一些特殊的东西以允许更新吗?

修改

这是饮料表格

class CoffeeForm(forms.ModelForm):
class Meta:
    model = Drink
    fields = ('time', 'location', 'type')

def __init__(self, *args, **kwargs):
    super(forms.ModelForm, self).__init__(*args, **kwargs)

    coffee_category = Category.objects.get(name='coffee')
    coffee_drink_types = DrinkType.objects.filter(category=coffee_category.id)
    self.fields['type'].choices = ((x.id, str(x)) for x in coffee_drink_types)

饮料模型:

class Drink(models.Model):
    time = models.DateTimeField('time', default=datetime.datetime.now)
    location = models.ForeignKey(Location)
    type = models.ForeignKey(DrinkType)

**编辑**

添加网址:

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^edit/$', views.edit, name='edit'),
    url(r'^edit/(?P<coffee_id>[0-9]*)/$', views.edit, name='edit')
]

4 个答案:

答案 0 :(得分:1)

调用CoffeeForm时,您应该使用ModelForm,而不是super

class CoffeeForm(forms.ModelForm):
    class Meta:
        model = Drink
        fields = ('time', 'location', 'type')

    def __init__(self, *args, **kwargs):
        super(CoffeeForm, self).__init__(*args, **kwargs)

答案 1 :(得分:0)

如果具有给定id的饮料不存在,则

get_object_or_404错误。

你确定对/ edit / 1进行了POST吗?因为如果表单操作没有ID,则会创建一个新的饮料。

我建议您使用单独的创建和编辑视图。可能使用基于类的视图,但如果你有理由不使用它们,这样的事情可能会起作用:

def create_coffee(request):
    if request.method == 'POST':
        form = CoffeeForm(request.POST)
        if form.is_valid():
            coffee = form.save()
            return redirect(reverse('edit_coffee', kwargs={'coffee_id': coffee.pk}))
    else:
        form = CoffeeForm()

    return render(request, 'create.html', {'coffee_form': form})


def edit_coffee(request, coffee_id=None):
    coffee = Drink.objects.filter(pk=coffee_id).first()
    if not coffee:
        return redirect(reverse('create_coffee'))
    else:
        if request.method == 'POST':
            form = CoffeeForm(request.POST, instance=coffee)
            if form.is_valid():
                form.save()
        else:
            form = CoffeeForm(instance=coffee)

        return render(request, 'edit.html', {'coffee_form': form})

答案 2 :(得分:0)

不知道你是否还在检查这个问题,我发现这也在寻找同样的问题,我设法解决了这个问题。 在我的情况下,问题是我为新对象和现有对象使用了相同的模板,并且表单返回并创建了新实例,我解决了此时使用多个模板创建多个视图。

我进入正轨的那一点是当我从表单中删除action="/add"时,我发现没有任何反应:)。我看到您使用相同的模板而不是从视图中更改它,因此您可能还需要这样做。 如果你无法解决这个帖子你的模板,我很乐意提供帮助,因为它可以帮助我学习django! :)

答案 3 :(得分:0)

有同样的问题,我的原因是在Forms.py中覆盖了默认方法form.save()。因此,我决定采用2种方法(用于保存和更新)。更新方法应继承默认的save()方法

super(ArticleForm, self).save(*args, **kwargs)

这不是必需的,但对我来说是必要的,因为我应该保存一些不是表单中的数据。

def save(self, *args, **kwargs):
    new_article = Article.objects.create(
        title=self.cleaned_data['title'],
        text=self.cleaned_data['text'],
        image=self.cleaned_data['image'],
        author_id=self._user.id
    )
return new_article

def update(self, article_id, *args, **kwargs):
    super(ArticleForm, self).save(*args, **kwargs)
    new_article = Article.objects.get(id=article_id)
    return new_article

此方法可能不会返回任何内容,但我需要在views.py中添加new_article对象

但是您可以采取另一种方式。只需在表单的def init 中定义author_id字段即可。

在这里您可以了解更多信息:Habr