Say I have a model like this.
class Job(models.Model):
client = models.ForeignKey(Contacts, null=True)
and lets say I have job j. I know I can access the client belonging to j like this
j.client
but there is also
j.client_id
So my question is how does accessing j.client work?
Does django store client__id then when j.client is called it does a query to find the correct object?
Or is the object reference stored to j and accessing client__id is getting the id from the Contact object?
I've looked around the source code a bit but couldn't find the answer to my question
ForeignKey is a Django ORM field-to-column mapping for creating and working with relationships between tables in relational databases. ForeignKey is defined within the django. db. models.
Django automatically creates an index for all models. ForeignKey columns.
Update: ForeignKey. limit_choices_to allows to specify either a constant, a callable or a Q object to restrict the allowable choices for the key.
What you are probably talking about is client
and client_id
(single underscore).
The client_id
attribute is a regular (integer) attribute. This is the foreign key that is saved to the database. You will only ever see a client_id
column in the database, even though you specify the ForeignKey
as client
.
The client
attribute is an object descriptor instance. It is a special class that overrides the __get__
and __set__
methods, so settings and accessing that attributes invokes that class's methods. This is the magic that gives you access to the actual related model instance. __get__
will retrieve the correct model instance from the database if it isn't loaded already, based on the client_id
attribute. __set__
will also set the client_id
attribute to the primary key of the related object, so that client_id
is always up-to-date.
Note that this attribute is also available in query lookups, and is quite handy. E.g., if you have just the primary key of a foreign object, and not the model instance itself, the following queries look very similar:
job = Job.objects.filter(client__id=pk)
job = Job.objects.filter(client_id=pk)
However, underneath the first query accesses an attribute on the related object (double underscore) and performs an OUTER JOIN
. The second query only ever accesses a local attribute, thus not having to perform the OUTER JOIN
statement and saving performance.
This is explained in the docs:
https://docs.djangoproject.com/en/dev/ref/models/fields/#database-representation
In the database there is only client_id
field (single underscore)
On the model instance you will have client
attribute, when you access it this will cause Django to load the related object from the db and instantiate as another model instance.
You will also have client_id
attribute (one underscore) which has the primary key value of the related object, as stored in the db field.
When doing ORM queries you are able to use client__id
(double underscore) syntax to lookup against fields on the related model, eg you could also do client__name
if Client
model had a name
field. This will become a SQL JOIN query across both models.
eg
Job.objects.get(client__id=1)
Job.objects.filter(client__name='John')
client = Client.objects.get(pk=1)
Job.objects.get(client=client)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With