The Django model field API provides a ForeignKey
[Django-doc]
and a OneToOneField
[Django-doc].
Both fields share most of the same parameters: in fact a
OneToOneField
is a subclass of a
ForeignKey
. In the constructor, it sets the
unique=…
parameter [Django-doc] to
True
. If you create a
ForeignKey
with unique=True
,
then Django will raise an warning that explains that a
OneToOneField
is probably more appropriate.
The fact that a OneToOneField
is unique
means thus that for two records, the
OneToOneField
s can not refer to
the same record.
As a result if a Profile
has a
OneToOneField
to a User
model,
it means that two Profile
s can not refer to
the same User
, and thus a User
record has at most one related
Profile
. This is important: it means that
if we access the Profile
(s) of a
User
we get zero or one records. As a
result the designers of Django specified the related_name=…
[Django-doc]
of a OneToOneField
, not as
modelname_set
, but
modelname
. Indeed, you access the
Profile
that belongs to a User
object my_user
with
my_user.profile
(given you do not override
the related_name=…
parameter). This will
look for a Profile
object, and returns that
object if it can be found, otherwise it raises a
RelatedObjectDoesNotExist
exception. For a
ForeignKey
, the default would have been
profile_set
, and
my_user.profile_set
is a RelatedManager
[Django-doc]:
accessing this attribute would thus never raise an
error, and one can then access all the related
Profile
s with
my_user.profile_set.all()
.
A OneToOneField
is also used for
inheritance. If one has a concrete model named
Vehicle
, and a subclass of that model named
Car
, then Django will add a "hidden"
OneToOneField
named
modename_ptr
with
modelname
the name of the model of
the parent in lowercase, so in this case, it will be
vehicle_ptr
. One might want to provide a
field themselves, for example to give this a different
name, or to add certain behavior. Therefore a
OneToOneField
accepts an extra .parent_link=…
parameter [Django-doc] which is a boolean
that can be set to True
in case the
OneToOneField
acts as a link to that
parent.
The OneToOneField
often gives the wrong
impression that if a model Profile
has a
OneToOneField
to a User
model
for example, it somehow would guarantee that a user has
exactly one Profile
. That is not
the case: a OneToOneField
guarantees, if it
is not null=True
, that a
Profile
has exactly one related
User
model, and a User
has
at most one related Profile
. It
thus will not automatically create a
Profile
object in case a User
object is constructed. Perhaps a more appropriate name
might have been an OptionalToOneField
.
Summary
ForeignKey | OneToOneField | |
---|---|---|
relation type | many-to-one | optional-to-one |
uniqueness | not unique (unless specified) | always unique |
default
related_name | modelname_set | modelname |
related relation | RelatedManager | trying to fetch the reverse object |
parameters | extra
parent_link=… |