1

I have 2 Models in Django. ModelA and ModelB. Here is the code for both these models.(This is just example code.)

class ModelA(models.Model):
    # Single Insert
    name=model.CharField(max_length=100)

class ModelB(models.Model):
    # Multiple Insert
    model_a=models.ForeignKey(ModelA,on_delete=models.CASCADE)
    address=models.CharField(max_length=250)

Now how can i insert data in both these models using a single Database Query(i.e Database should be hit only once) using ORM in Django.More specifically is it possible to do this via Django REST serializers cause it can handle the CRUD operations in an optimized manner.

I know that i can do this via multiple serializers but that will lead to the databse getting hit multiple times or i can also do this via stored procedures in MySQL.

Dhruv Marwha
  • 1,064
  • 2
  • 14
  • 26
  • This is not how the ORM works and how ReST should be done, so could you please explain your motivation? – Klaus D. Aug 07 '18 at 06:21
  • My Motivation here is to enter data in multiple tables while minimising database hits.Say for example, i have a form which has 3 fields:name,Permanent address and current address.In Django, i have defined a model which accepts the name and an address model which has a foreign key to the name model.So when this data comes to my django view,i should be able to insert data into both these models at the same time in order to lessen the load on the database. We want to try this procedure via the serializer as it can take care of most of the things for me. – Dhruv Marwha Aug 07 '18 at 06:30
  • My question went more in the direction of why you want to minimize database hits. – Klaus D. Aug 07 '18 at 06:41
  • I dont think you can insert into two different tables with one query. See [this](https://stackoverflow.com/a/5178713/5312750), if it helps. – Sachin Aug 07 '18 at 06:43
  • @KlausD. It is better to minimise database hits to reduce the load on the database itself and basically i wanted to optimise the database operation.It is not necessary but i fell that it's better to optimise code if i can do so in the beginning. – Dhruv Marwha Aug 07 '18 at 06:52
  • The only way I can think of is to combine the data into one table and allow blank or allow null. Other than that, I think it's not possible even using raw SQL. – Lian Aug 07 '18 at 11:17

1 Answers1

0

You can make use of bulk_create and bulk_update method, You need to create a list of objects manually.

In your case ModelA is parent class and ModelB is a child.

It means one object of ModelA can be related to more than one objects of ModelB

If you have request.data in your API endpoint seems like.

received_data = [
  {
    "name": "model_a_obj_1",
    "children": [
      {
        "address" : "some_address"
      }, 
      {
        "address" : "some_other_address"
      }
    ] 
  }, {}, {}, ...
]

Now the first step is to create two lists, a list of children list and a list of parent objects.

model_a_obj_list = []
model_b_children_list = []

for obj in received_data:
   children_list = []
   for child in obj.children:
      children_list.append(ModelB(**child))
   model_b_children_list.append(children_list)
   model_a_obj_list.append(ModelA(name=obj.name))

Now create parent objects first i.e ModelA and then loop over actual objects of ModelA to assign its pk to corresponding ModelB objects

model_a_objs = ModelA.objects.bulk_create(model_a_obj_list)

model_b_obj_list = []
for i, a_obj in enumerate(model_a_objs):
    model_b_obj_sub_list = model_b_children_list[i]
    for b_obj in model_b_obj_sub_list:
        b_obj.model_a = a_obj
        model_b_obj_list.append(b_obj)

Now we have ModelB objects with ModelA references. Now just create ModelB objects.

ModelB.objects.bulk_create(model_b_obj_list)

Remember the bulk_create method doesn't use the .save() method of Model class behind the scene, so any post_save logic must be calculated while creating objects list for bulk_create

This solution will hit the DB 2 time one for each Model

Satendra
  • 6,755
  • 4
  • 26
  • 46