Pannu
Pannu

Reputation: 2657

Model save update only specific fields

I'm trying to write a webservice which performs inserts or updates. The request is a post with headers,value which contains table name, column name and the value to be set for each column, I'm parsing the request headers and forming a parameter dict

def handel_request(request): if request.method == "POST":
        param_dict = formParmDict(request)
        ##if insert param_dict["Model"] is {'pk':1,'field1':100,'field2':200}
        ##if update param_dict["Model"] is {'pk':1,'field1':100}
        Model(**param_dict["Model"]).save() ## if update then sets field2 to null
        return HttpResponse()
    else:
        return HttpResponseBadRequest()

This works fine while the .save() performs an insert. In case of update ie if param_dict["Model"] contains {pk:1, field1:somevalue} to be updated then it sets the rest of the fields other than the ones specified in param_dict["Model"] to null. why is that? am I doing something wrong? isn't save suppose to update only the fields specified?

Upvotes: 1

Views: 1327

Answers (2)

genry
genry

Reputation: 101

Maybe you shoul use some function like this:

def insert_or_update(param_dict):
    pk = param_dict.get('pk', None)
    if pk:
        Model.objects.filter(pk=pk).update(**param_dict)
    else:
        Model(**param_dict)
        Model.save()

Upvotes: 0

Josh Smeaton
Josh Smeaton

Reputation: 48720

This is not how you're supposed to update.

Model(**param_dict["Model"]).save()

You're creating a new instance with the same id. Instead, you should get the instance, and then update it appropriately.

m = Model.objects.get(id=param_dict['id'])
m.field = param_dict['some_field']
m.save()

Or, you can use the Manager update method:

Model.objects.filter(id=param_dict['id']).update(**param_dict['Model'])

There's also the get_or_create method if you're not sure whether or not the record already exists.

You can try using a REST framework, like tasty-pie or django-rest-framework, which might alleviate some problems you're having.

Edit:

A brief summary about how save works in django. This is what I meant about whether or not an INSERT or an UPDATE is happening. Unless your post_data dict contains empty values for all the fields, read the documentation on how save works for a more thorough understanding of how django works.

So, what is happening in your case is this:

dict = {'id': 1, 'field1': 'my_value'}
m = Model(**dict)
m.id       # 1
m.field1   # my_value
m.field2   # None (because you haven't set it, it defaults to None
m.save()   # UPDATEs the existing instance with id 1 with ALL of the values of `m`

So, you're saving an instance that contains None values. That's why I'm suggesting you do a get, so that all the correct values are filled, before saving to the database.

Upvotes: 2

Related Questions