How do I update an already existing row when using ModelForms?
Asked Answered
P

4

16

I have a question on how to update an existing row in my database when one of the fields is my primary key. I am using ModelForm and Django-Piston - my main goal here is to have RESTful Post send to my webservice. I am able to have initial Posts be sent correctly (i.e. that Primary key value doesn't exist yet). The problem is when I want to update a value where the Primary key already exists - when I issue a f.is_valid() it fails because "this UniqueIdentifier already exists". How can I do form validation using ModelForms to update an existing row?

My 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'}),
)
Picardi answered 23/11, 2009 at 0:7 Comment(1)
If an answer gave you the information you needed, you should accept it (click the checkmark).Niphablepsia
S
20

The django docs give a simple example of how to create "a form to change an existing [[entity]]":

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

If as it seems you want to use the same flow both for inserting new objects and changing existing ones, you'll have to instantiate the form separately depending on whether looking for the primary key succeeds (existing object) or fails (new object)!-)

Sinus answered 23/11, 2009 at 0:34 Comment(1)
When the form.save() is applied on the form, the instance should be updated with the form data? My form is saving it to new instance, it is making itself.Arboreal
H
18

To update an existing row (or object in ORM-speak), you have to tell the ModelForm what instance to use when instantiating it:

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

I'm not sure where you get myobject from using piston, though, but your question seems to imply that you solved that particular problem already.

Hooey answered 23/11, 2009 at 0:28 Comment(1)
This was the correct answer for my problem. It's documented (though hard to find) here docs.djangoproject.com/en/dev/topics/forms/modelforms/… (see the last example in the code box)Imputation
P
6

Here is a more complete solution not using any Class based views, bringing together the other answers and comments on this page.

I have it working as a reply to a 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?')   
Penhall answered 7/1, 2017 at 13:0 Comment(0)
C
0

This is what I did to update or create depending on if the entity exists:

# 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 doesn't 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()
Claypool answered 2/8, 2018 at 17:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.