70👍
A OneToOneField
is very similar to a ForeignKey
with unique=True
. Unless you are doing multiple table inheritance, in which case you have to use OneToOneField
, the only real difference is the api for accessing related objects.
In the Django docs it says:
Conceptually, this is similar to a
ForeignKey
withunique=True
, but the “reverse” side of the relation will directly return a single object.
Let’s show what that means with an example. Consider two models, Person
and Address
. We’ll assume each person has a unique address.
class Person(models.Model):
name = models.CharField(max_length=50)
address = models.ForeignKey('Address', unique=True)
class Address(models.Model):
street = models.CharField(max_length=50)
If you start with a person, you can access the address easily:
address = person.address
However if you start with an address, you have to go via the person_set
manager to get the person.
person = address.person_set.get() # may raise Person.DoesNotExist
Now let’s replace the ForeignKey
with a OneToOneField
.
class Person(models.Model):
name = models.CharField(max_length=50)
address = models.OneToOneField('Address')
class Address(models.Model):
street = models.CharField(max_length=50)
If you start with a person, you can access the address in the same way:
address = person.address
And now, we can access the person from the address more easily.
person = address.person # may raise Person.DoesNotExist
1👍
When you access a OneToOneField
you get the value of the field you queried. In this example a book model’s ‘title’ field is a OneToOneField
:
>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'
When you access a ForeignKey
you get the related model object, which you can then preform further queries against. In this example the same book model’s ‘publisher’ field is a ForeignKey
(correlating to the Publisher
class model definition):
>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'
With ForeignKey
fields queries work the other way too, but they’re slightly different due to the non-symmetrical nature of the relationship.
>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]
Behind the scenes, book_set is just a QuerySet
and can be filtered and sliced like any other QuerySet
. The attribute name book_set is generated by appending the lower case model name to _set
.
I hope this helps illustrate the differences between the relationships created.
- [Django]-ManyRelatedManager object is not iterable
- [Django]-Django – Rotating File Handler stuck when file is equal to maxBytes
- [Django]-In django, how do I sort a model on a field and then get the last item?