15

I've a model

from django.contrib.auth.models import User

class ModelA(models.Model):
    phone = models.CharField(max_length=20)
    user = models.ForeignKey(User)

I need to insert the data into this model. I've an endpoint hosted which provides me the following data {'phone':XXXXXXXX, 'user_id':123}.

Now when I insert the data into this model like

obj = ModelA.objects.create(phone=data['phone'], user = data['user_id]

It throws an error saying

Cannot assign "u'123'": "ModelA.user" must be a "User" instance.

Agreed, since because with django orm you can interact in terms of objects and not numbers. Hence I first found the object of the User and then created ModelA object.

user_obj = User.objects.get(id=data['id']
modelobj = ModelA.objects.create(phone=data['phone'], user = user_obj

Till here its all working fine.

Now, my question is that is there any other way of assigning/creating ModelA object directly using user_id not User object, since it first involves quering User Model and then inserting. Its like an extra read operation for every ModelA object created.

Praful Bagai
  • 16,684
  • 50
  • 136
  • 267

2 Answers2

17

As can be seen in my historic comments, the accepted answer is not really correct. So as @yekta requested I re-submit my comments:

To create the parent model, use integer value like:

ModelA.objects.create(phone=data['phone'], user_id=1)
Vlad Lyga
  • 1,133
  • 9
  • 10
7

(I keep getting votes for an answer that is wrong. If the database you are using has actual integrity checking, you can just use attr_name_id to insert the related object.

Wish I could just delete it. Look at the answer below.)

Basically, you can't do that. Django's ORM is expecting an object and not just a key. It's the price to pay to have an extra layer of abstraction that is supposed to check for integrity at the application level, instead of the DB-level.

If performance is a problem (and in the general case it isn't), you can make the read operation of the User object as light as possible. The only function will return a queryset of objects, forcing the select to retrieve only the id column, which is surely indexed.

user = User.objects.only('id').get(id=data['user_id'])
obj = ModelA.objects.create(phone=data['phone'], user=user)
lullis
  • 304
  • 4
  • 7
  • 2
    Not completely correct, just for future people who are going to read this question there is a way, you can do `ModelA.objects.create(phone=data['phone'], user=user_id) #in case ModelA related to user via user id, for other fields you can do user_name` – Vlad Lyga Sep 16 '15 at 12:10
  • 3
    The correct code is: ModelA.objects.create(phone=data['phone'], user_id=1) – Vlad Lyga Sep 16 '15 at 12:21
  • Just for clarification, Vlad's second comment works (i.e. you can disregard the code in the first comment). – Ben Jun 25 '17 at 19:03