Sygol
Sygol

Reputation: 197

Using '_id' in Django

I am a bit confused how Django handles '_id' property when we use ORM with some models that use foreign key. For example:

class CartItem(models.Model):
    user = models.ForeignKey('accounts.CustomUser', related_name='carts', on_delete=models.CASCADE, verbose_name='User')
    product = models.ForeignKey('pizza.Product', related_name='carts', on_delete=models.CASCADE, verbose_name=_('Product'))
    quantity = models.SmallIntegerField(verbose_name=_('Quantity'))

And when I use ORM with 'filter' I can easily use something like:

CartItem.objects.filter(user=1, product=1, quantity=1)

And Django kind of 'see' that I refer to 'id', but when I use exacly the same line of code, but with 'create' instead of 'filter':

CartItem.objects.create(user=1, product=1, quantity=1)

Then it throws an error saying:

Cannot assign "1": "CartItem.user" must be a "CustomUser" instance.

And to create it I need to use:

CartItem.objects.create(user_id=1, product_id=1, quantity=1)

Why is that? Is there some rule here that I don't understand?

Upvotes: 6

Views: 5313

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476574

This is the database representation of the ForeignKey [Django-doc]. A reference to model object is represented as:

Behind the scenes, Django appends "_id" to the field name to create its database column name. In the above example, the database table for the Car model will have a manufacturer_id column. (You can change this explicitly by specifying db_column) However, your code should never have to deal with the database column name, unless you write custom SQL. You’ll always deal with the field names of your model object.

So you could say that Django will construct a "twin" column, with an _id suffix. This column has the same type as the type of the primary key of the model you target, and that column will thus contain the primary key of the model object you use. Note that you can use a different field to which you target by specifying the to_field=… parameter [Django-doc].

The ForeignKey itself thus does not exists at the database, that is the logic of Django that will use the primary of that object, and store that in a column with, by default, an _id suffix.

Upvotes: 4

Related Questions