Как обновить уже существующую строку при использовании ModelForms?

У меня вопрос о том, как обновлять существующую строку в моей базе данных, когда одним из полей является мой первичный ключ. Я использую ModelForm и Django-Piston - моя главная цель здесь - отправить RESTful Post на мой веб-сервис. Я могу правильно отправлять начальные сообщения (т.е. Что значение основного ключа еще не существует). Проблема заключается в том, когда я хочу обновить значение, когда ключ Primary уже существует - когда я выдаю f.is_valid(), он терпит неудачу, потому что "этот UniqueIdentifier уже существует". Как я могу выполнить проверку формы с помощью ModelForms для обновления существующей строки?

Мои модели .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'}),
)

Ответ 1

django docs дают простой пример того, как создать "форму для изменения существующего [[entity]]":

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

Если вам кажется, что вы хотите использовать один и тот же поток как для вставки новых объектов, так и для изменения существующих, вам необходимо создать экземпляр формы отдельно в зависимости от того, выполняется ли поиск первичного ключа (существующий объект) или отсутствует (новый объект) -!)

Ответ 2

Чтобы обновить существующую строку (или объект в ORM-talk), вы должны сообщить ModelForm, какой экземпляр использовать при его создании:

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

Я не уверен, что вы используете myobject от использования поршня, но ваш вопрос, похоже, подразумевает, что вы решили эту конкретную проблему уже.

Ответ 3

Вот более полное решение, не использующее какие-либо классовые представления, объединяющее другие ответы и комментарии на этой странице.

У меня это работает как ответ на 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?')   

Ответ 4

Это то, что я сделал, чтобы обновить или создать в зависимости от того, существует ли сущность:

# first see the DeviceModel exists and should simply be updated

try:
    instance = DeviceModel.objects.get(mycolumn=data['mycolumn'])
    f = DeviceModelForm(data, instance=instance)
except DeviceModel.DoesNotExist:
    # DeviceModel does not exists, so we create a new one
    f = DeviceModelForm(data)
except DeviceModel.MultipleObjectsReturned:
    # our query found multiple DeviceModel
    # either update them all or throw an error
    print("Found multiple DeviceModels")

if f.is_valid():
    f.save()