22

Is there a way to not have to pass in a model instance for a foreign key when create a new model? Let's say I have the following models:

class Foo(models.Model):
    description = models.CharField(max_length=100)

    class Meta:
         db_table = u'foo'

class Bar(models.Model):
    info = models.CharField(max_length=100)
    foo = models.ForeignKey('Foo')

    class Meta:
         db_table = u'bar'

The later a post request comes in to a view - I know the the id of a foo record and just want to insert a record into the bar table.

if I do:

new_bar = Bar(info="something important", foo=foo_id)
new_bar.save()

I get a ValueError saying "Cannot assign "546456487466L": "Bar.foo" just be a "Foo" instance.

So, I get it... it wants me to have an actual instance of the Foo model. I understand that I can just do a get on Foo and then pass it in. But, there seems like there must be a way to override this functionality. I have done some googling and reading the docs, and raw_id_fields in admin seems to be the basic idea. (which is to say, allow a raw id here). But, don't see this option on the ForeignKey field.

It seems very inefficient to have to make a round trip to the database to get an object to get the id (which I already have). I understand that doing the round trip validates that the id exists in the database. But, hey... that's why I'm using a RDBMS and have foreign keys in the first place.

Thanks

David S
  • 12,967
  • 12
  • 55
  • 93

1 Answers1

26
new_bar = Bar(info="something important", foo_id=12345)
new_bar.save()

You can also get foreign key values directly. Some kind of optimization.

netvope
  • 7,647
  • 7
  • 32
  • 42
San4ez
  • 8,091
  • 4
  • 41
  • 62
  • This worked... I still had problems until I figured something out. going to add 1 little note here and edit the answer above. In my example above, I actually was over simplify a bit. In the REAL models, "foo" the primary key of the table was not "id". And the foreign was not "foo_id". But, you STILL need to use the fieldname+"_id" to get it to work. – David S May 16 '12 at 22:16
  • 1
    Isn't this strange that its not a double underscore, since id is a field of Foo. You use a double underscore in querysets at least. – radtek Mar 23 '15 at 22:02
  • 1
    @radtek that is because you are not using Foo's id field, you are using Bar's foo_id field. If you use some sort of database client you will see that `appname_foo` has a column `id` and `appname_bar` has a column `foo_id`. I mean otherwise how would you know which Foo goes to each Bar? So in this case even in querysets you would NOT (and should NOT) use a double underscore when dealing with id's, (you avoid a join that way). – semicolon Aug 04 '15 at 22:38