Reputation: 5762
I am getting a PUT
request which is having array of json objects for same non-primary ID.
Example:
{
"some_non_pk_id":101,
"user_entries":[
{
"name":"foo",
"height":1.56
},
{
"name":"bar",
"height":1.76
},
.
.
.
]
}
I need to upsert the object in a table which looks something like this
+----+----------------+------+--------+
| id | some_non_pk_id | name | height |
+----+----------------+------+--------+
| 1 | 101 | foo | 1.56 |
| 2 | 101 | bar | 1.76 |
+----+----------------+------+--------+
The url of the PUT
/PATCH
request will be /api/details/?some_non_pk_id=101
. I am not sure how to override the update
or partial_update
of ModelViewSet
to upsert this.
I am ok if the request body can be changed to something like this. Changing the request bosy is in my control.
[
{
"some_non_pk_id":101,
"name":"foo",
"height":1.56
},
{
"some_non_pk_id":101,
"name":"bar",
"height":1.76
}
]
Upvotes: 0
Views: 408
Reputation: 41258
It looks from your example like you don't want to do an upsert per-se, but rather to replace a set of database items (those with a given some_non_pk_id
) with a set of new items.
If this is your goal, then what you want to do is in a transaction, delete the old set and create the new set.
Taking your initial payload as a guide, you could do something like this:
def update(self):
# Replace the following line with however you plan to get the payload
payload = json.loads(self.request.body)
with transaction.atomic():
identifier = payload["some_non_pk_id"]
# replace `YourModel` with the actual name of your model
YourModel.objects.filter(some_non_pk_id=identifier).delete()
for item_kwargs in payload["user_entries"]:
item_kwargs["some_non_pk_id"] = identifier
YourModel.objects.create(**item_kwargs)
Upvotes: 1