如何在使用ModelForms时更新已存在的行?

16 投票
4 回答
14645 浏览
提问于 2025-04-15 16:16

我有个问题,想知道如何在数据库中更新一行数据,而这行数据的某个字段是我的主键。我正在使用ModelForm和Django-Piston,主要目的是让RESTful的POST请求能发送到我的网络服务。我可以正确发送初始的POST请求(也就是说,那个主键的值还不存在)。但问题是,当我想更新一个已经存在的主键的值时,调用f.is_valid()会失败,因为提示“这个唯一标识符已经存在”。我该如何使用ModelForms进行表单验证,以更新已存在的行呢?

我的models.py文件:

from django.db import models
class DeviceModel(models.Model):
    uniqueIdentifier = models.CharField(primary_key=True, max_length=100)
    deviceToken = models.CharField(max_length=100)

forms.py文件:

from django import forms
from models import DeviceModel
class DeviceModelForm(forms.ModelForm):
    class Meta:
        model = DeviceModel

handlers.py文件:

class DeviceHandler(BaseHandler):
allowed_methods = ('POST', 'GET', 'DELETE',)
def create(self, request):
    f = DeviceModelForm(request.POST)
    if f.is_valid():
        new_object = f.save()
        return new_object
    return rc.BAD_REQUEST

urls.py文件:

from django.conf.urls.defaults import *
from piston.resource import Resource
from api.handlers import DeviceHandler

device_handler = Resource(DeviceHandler)

urlpatterns = patterns('',
    (r'^api/$', device_handler, {'emitter_format': 'json'}),
)

4 个回答

6

这里有一个更完整的解决方案,没有使用任何基于类的视图,结合了这个页面上其他答案和评论。

我已经让它可以作为对jquery ajax的回复工作了。

def save_product(request):                                                                       
    if request.method == "POST":                                                                 
        # first get the model pk we are looking for
        postpk = request.POST.get('pk', None)

        # get the model from the db                                                
        model, created = Product.objects.get_or_create(pk = postpk)                          

        # create the from based on the model, but with the 
        # request data overriding the model data                                                 
        form = ProductForm(request.POST, instance = model)

        # save if valid                                       
        if form.is_valid():                                                                      
            form.save()                                                                          
            return HttpResponse("saved")                                         
        else:                             
            # will go to the the ajax error: data.responseText                                                       
            return HttpResponseNotFound("%s" % (form.errors))                                    
    else:                                                                                        
        return HttpResponseNotFound('eh? this was not a Post?')   
18

要更新一个已经存在的行(或者在ORM中称为对象),你需要告诉ModelForm在创建它的时候用哪个实例:

f = DeviceModelForm(request.POST, instance=myobject)

不过我不太确定你是从哪里得到myobject的,使用piston的时候,不过你的问题似乎暗示你已经解决了这个特定的问题。

20

Django的官方文档里有一个简单的例子,讲的是如何创建一个“用来修改已有对象的表单”。

>>> article = Article.objects.get(pk=1)
>>> form = ArticleForm(instance=article)

如果你想用同样的方式来处理添加新对象和修改已有对象的情况,你就需要根据查找主键是否成功来分别创建表单。如果查找成功,说明是已有对象;如果查找失败,那就是新对象了!

撰写回答