【问题标题】:model.AutoField - form.save() creates new records (INSERT) instead of updating existingmodel.AutoField - form.save() 创建新记录 (INSERT) 而不是更新现有记录
【发布时间】:2011-12-10 19:33:32
【问题描述】:

情况:有一个现有的 mysql 数据库,其中包含一些数据。对于这个例子,我只使用了两个字段; id主题id 被定义为带有 *auto_increment* 选项的整数,而 subject 只是一个普通的 varchar。代码:

型号

class AList(models.Model):
    id=models.AutoField(primary_key=True, db_column='ID')
    subject=models.CharField(max_length=200, db_column='SUBJECT')
    class Meta:
        db_table = u'alist'

表格

class AForm(ModelForm):
    class Meta:
        model=AList

查看

def alistForm(request,a_id=None):
    if a_id:
        a=AList.objects.get(id=a_id)
        form=AForm(instance=a)
    else:
        form=AForm(request.POST or None)
    return render_to_response('aform.html',{'form':form},context_instance=RequestContext(request)

def alistPost(request):
    form=AForm(request.POST or None)
    if form.is_valid():
        form.save()

问题描述: 当表单向 alistPost 函数发送新数据时,form.save() 会插入一条新记录。但是,当我编辑一个已经存在的记录时,它也会作为新记录插入......并且没有按应有的方式更新。

尝试将 id 从 AutoField 更改为 IntegerField 会改变行为:修改记录会使 form.save() 修改现有的,在尝试插入新记录时失败,因为它没有 id。

问题: 我是否必须手动从数据库中获取一个新的 ID 值并强制 Django 将其用于这条新记录,或者有没有办法让 Django 自动确定它是否应该使用 INSERT 或 UPDATE?

【问题讨论】:

    标签: django django-models django-forms django-database


    【解决方案1】:

    dragonon 是在正确的轨道上,但你的评论是有道理的。更好的模式是这样的:

    if a_id:
        a = AList.objects.get(id=a_id)
    else:
        a = AList()
    if request.POST:
        form = AForm(request.POST, instance=a)
        ...
    else:
        form = AForm(instance=a)
    

    【讨论】:

    • 感谢您的回答。我将模式更改为您提供的模式,但它仍然无法按预期工作。我还将模型中的 id 更改为 IntergerField(primary_key=True)。这是因为 AutoField 总是在数据库中生成一个新条目。我现在继续前进的方式是检查表单中的 id 字段是否存在,并手动从数据库中获取最大值......并将新值手动设置为更高的值(我知道......可能的竞争条件)。不太喜欢这种方法,但是现在我已经把头撞到这个问题上太久了...... :)
    • form = AForm(request.POST, instance=a) 帮了我大忙。
    【解决方案2】:

    这就是我所做的:

    def someView(request,id=None):
       instance = form = None
    
       ...
          ...
       elif request.method == 'POST':
    
            if id != None:
                instance = SomeClass.objects.get(id=id)
                form = AForm(request.POST,instance=instance)
            else:
                form = AForm(request.POST) 
    
            if form.is_valid():
    
               instance = form.save()
               if not id:
                   return redirect('edit',id=instance.id)
            else
                ...
            ...
    

    网址:

    url(r'^addedit/$', 'som.views.someView', name='edit'),
    url(r'^addedit/(?P<id>.*)/$', 'som.views.someView', name='edit'),
    

    所以在/addit/创建对象后,用户被重定向到/addit/1234/

    【讨论】:

      【解决方案3】:

      问题是您在一个单独的函数中执行 POST,而您不向表单提供 instance 参数。

      尝试像这样将函数合并为一个:

      def alistForm(request, pk)
          alist = get_object_or_404(AList, pk=pk)
          form = AFrom(request.POST or None, instance=alist)
          if request.method == 'POST':
              if form.is_valid():
                  form.save()
          ...
      

      【讨论】:

      • 感谢您的回答。已尝试将其重写为更像您的示例,但是 pk-part 存在问题。没有 pk,它会失败并返回 404。关键是没有 pk 的调用,没有要传递的实例,并且表单应该是空的。使用 pk,表单应该填充现有数据,并且提交应该更新数据库。这就是失败的地方。在模型中使用 AutoField,将修改后的数据作为新数据插入,同时使用 IntegerField 正确更新它(但由于缺少 pk 无法插入新数据(primary_key=True 可能是这里的问题?)。
      猜你喜欢
      • 2023-01-12
      • 2012-07-25
      • 2021-03-30
      • 1970-01-01
      • 2015-10-07
      • 2020-06-20
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多