How to send an array of json object in PUT request for non-primary Key in Django?

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

Answers (1)

Zags
Zags

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

Related Questions