Django modelformset创建新记录,而不是更新现有记录 [英] Django modelformset creates new record instead of updating existing one

查看:170
本文介绍了Django modelformset创建新记录,而不是更新现有记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可以有一个或多个模型的系统。我已经使用manytomany字段在数据库中建模了这种关系。以下代码用于以单一形式编辑系统及其相关联的方法。



通过填写其表单并按下来添加新的方法仅首次提交作品 。如果我再做一个小的更改并再次提交,我会收到以下消息(由以下代码生成):

  METHODFORMSET。错误:[{},{'name':[u'Method with this Name already exists。']}] 

这是由于名称字段是唯一的,但应该具有更新,而不是创建新记录,即使我使用POST数据生成methodformset实例...



请注意,此行为仅适用于最后附加的方法实例,而不适用于表中已存在的实例。 p>

以下是相关代码,任何人都可以让我知道我在做错什么?

  def sysedit(request,sys_id):

system = System.objects.get(id = sys_id)
MethodFormSet = modelformset_factory(Method,form = MethodForm)

post = None
如果request.POST:
post = request.POST.copy()
如果添加_method'in request.POST:
post ['method-TOTAL_FORMS'] = repr(int(
post ['method-TOTAL_FORMS'])+ 1)

systemform = SystemForm(data = post,instance = system)

methodformset = MethodFormSet(data = post,prefix ='method',
queryset = Method.objects.filter(id__in = system.method。 all()))

如果methodformset.is_valid():
mfs = methodformset.save()
print'SAVED-method',mfs
for mf in mfs:
如果systemform.is_valid():
sp = systemform.save(mf)
print'SYSTEM',sp
else:
print'SYSFORMSET.ERRORS :',systemform.errors
else:
print'METHODFORMSET.ERRORS:',methodformset.errors

return render_to_response('sysedit.html',
{' systemform':systemform,
'metho dformset':methodformset,
'system':system},
context_instance = RequestContext(request))


class System(models.Model):
method = models.ManyToManyField(Method)
...

类方法(models.Model):
name = models.CharField(unique = True)
...

class MethodForm(ModelForm):
class Meta:
model = Method

class SystemForm(ModelForm):
def save(self,new_method = None,commit = True,* args,** kwargs):
m = super(SystemForm,self).save(commit = False,* args,** kwargs)
if new_method:
m.method.add(new_method)
如果提交:
m.save()
返回m

类Meta:
model = System
exclude =('method')

[ Sergzach的答案]:



问题不是如何处理 Metho d这个名字已经存在错误,但是为了防止这种情况首先发生。我认为实际的问题可能与模型处理新表单的方式有关。不管怎样,它总是试图为最后一个表单集创建一个新的实例,无论它是否已经退出。



所以如果在最后一个添加后不添加新的formset,那么modelformset会尝试重新创建最后一个formset(即使它只是在以前的提交)。



最初的情况是我在methodformset中有1个有效的Method实例和1个新的unbound实例。然后我填写表单并点击保存,这将验证两个方法并绑定第二个,然后将其保存到表中。
到目前为止一切都很好,但是如果我再次保存第二次出现错误。也许这与方法-TOTAL_FORMS = 2和method-INITIAL_FORMS = 1的事实有关。可能这是因为模型模型强制在第二种方法上创建吗?



任何人都可以确认/拒绝吗?



[周末后不要查看代码编辑]:



问题是由于我正在保存表单在视图中并保存后,我将原始的方法表单实例(从 保存)发送到模板。这个问题可以通过重新实例化

保存后的modelformset 来解决,使用查询器,而不是POST数据。



所以一般规则防止这样的错误,要么在保存之后进入不同的页面(完全避免它),要么使用上述解决方案。



在我发布这个作为解决方案之前我需要做更多的测试。

解决方案

我已经通过在保存后重新实例化了modelformset来解决问题(请参阅问题的底部)


I have a System that can have one or more Models. I have modeled this relationship in the database with a manytomany field. The code below is for editing the system and its associated methods in a single form.

Adding a new method by filling out its form and pressing submit works only the first time. If I then make a small change and submit again, I get the following message (generated by the code below):

METHODFORMSET.ERRORS: [{}, {'name': [u'Method with this Name already exists.']}]

This is caused by the fact that the name field is unique, but it should have updated, not created a new record, even though I am using the POST data to generate the methodformset instance...

Note that this behaviour only applies to the last appended method instance, not to ones that were already present in the table.

Here is the relevant code, can anyone let me know what I am doing wrong?

def sysedit(request, sys_id):

    system = System.objects.get(id=sys_id)
    MethodFormSet = modelformset_factory(Method, form=MethodForm)

    post = None
    if request.POST:
        post = request.POST.copy()
        if 'add_method' in request.POST:
            post['method-TOTAL_FORMS'] = repr(int(
                                                post['method-TOTAL_FORMS'])+ 1)

    systemform = SystemForm(data=post, instance=system)

    methodformset = MethodFormSet(data=post, prefix='method',
            queryset=Method.objects.filter(id__in=system.method.all()))

    if methodformset.is_valid():
        mfs = methodformset.save()
        print 'SAVED-method', mfs
        for mf in mfs:
            if systemform.is_valid():
                sp = systemform.save(mf)
                print 'SYSTEM', sp
            else:
                print 'SYSFORMSET.ERRORS:', systemform.errors
    else:
        print 'METHODFORMSET.ERRORS:', methodformset.errors

    return render_to_response('sysedit.html', 
            {'systemform': systemform, 
            'methodformset': methodformset, 
            'system': system},
            context_instance=RequestContext(request))


class System(models.Model):
    method = models.ManyToManyField(Method)
    ...

class Method(models.Model):
    name = models.CharField(unique=True)
    ...

class MethodForm(ModelForm):
    class Meta:
        model = Method

class SystemForm(ModelForm):
    def save(self, new_method=None, commit=True, *args, **kwargs):
        m = super(SystemForm, self).save(commit=False, *args, **kwargs)
        if new_method:
            m.method.add(new_method)
        if commit:
            m.save()
        return m

    class Meta:
        model = System
        exclude = ('method')

[EDIT after Sergzach's answer]:

The problem is not how to deal with the Method with this name already exists error, but to prevent that from occurring in the first place. I think the actual problem may have something to do with the way modelformsets deal with new forms. Somehow it looks like it always tries to create a new instance for the last formset, regardless of whether it already exits.

So if I do not add a new formset after the last one was appended, the modelformset will try to re-create the last one (even though it was just created on the previous submit).

The initial situation is that I have 1 valid Method instance and 1 new unbound instance in the methodformset. I then fill out the form and hit save, which validates both Methods and binds the 2nd one, which is then saved to the table. So far all is well, but if I then hit save the 2nd time the error occurs. Maybe this has to do with the fact that method-TOTAL_FORMS=2 and method-INITIAL_FORMS=1. Could it be that this causes modelformset to force a create on the 2nd Method?

Can anyone confirm/deny this?

[Edit after a weekend of not looking at the code]:

The problem is caused by the fact that I am saving the forms in the view and after saving, I am sending the original methodformset instance (from before the save) to the template. The problem can be solved by re-instantiating modelformset after the save, using the queryset and NOT the POST data.

So the general rule to prevent errors like this, is either to go to a different page after a save (avoid it altogether), or use the above solution.

Before I post this as THE solution, I need to do more testing.

解决方案

I have solved the problem by re-instantiating modelformset after the save (see edit at the bottom of the question)

这篇关于Django modelformset创建新记录,而不是更新现有记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆