71👍
What you are seeing is a reverse related object lookup.
In your example:
class Blog(models.Model):
pass
class Entry(..):
blog = Blog(..)
Now, given object e
of type Entry
, you would do e.blog
to access the related object Blog
– which is a forward relation.
The _set
is a reverse lookup class variable django puts in for you.
So, given object b
– you would do:
entries = b.entry_set.all()
The reason the reverse is a queryset is, ForeignKey is 1-to-many
relationship. Hence, the reverse is a queryset.
The _set
object is made available when related_name
is not specified.
44👍
Briefly speaking:
Suppose you have a model Car
and a model Wheel
. Wheel
has a foreign key relationship with Car
as follows:
class Car(models.Model):
pass
class Wheel(models.Model):
car = models.ForeignKey(Car, on_delete=models.CASCADE) # on_delete parameter is mandatory in Django 2.0
Let’s say w
is an instance of Wheel
, and c
is an instance of Car
:
>>> w.car # returns the related Car object to w
>>> c.wheel_set.all() # returns all Wheel objects related to c
Detailed explanation
Using the models defined above, a Wheel
object w
can get its associated Car
object by accessing the car
attribute: w.car
.
If a model has a ForeignKey
, instances of that model will have access to the related foreign object via a simple attribute of the model.
According to the official Django documentation:
Django also creates API accessors for the “other” side of the relationship – the link from the related model to the model that defines the relationship.
In this case, a Car
object c
has access to a list of all related Wheel
objects via the wheel_set
attribute: c.wheel_set.all()
.
If a model has a ForeignKey
, instances of the foreign-key model will have access to a Manager
that returns all instances of the first model. By default, this Manager
is named FOO_set
, where FOO
is the source model name, lowercased. This Manager
returns QuerySets
, which can be filtered and manipulated.
- [Django]-Altering database tables in Django
- [Django]-Handle `post_save` signal in celery
- [Django]-Django Model Field Default to Null
1👍
_set can access the child model which has the foreign key of the parent model.
For example, there is the child model Product
which has the foreign key of the parent model Category
as shown below:
"models.py"
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=20)
class Product(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
price = models.DecimalField(decimal_places=2, max_digits=5)
Then, you can access the child model Product
from the parent model Category
with _set
as shown below:
category_obj = Category.objects.all()[0]
product_obj = category_obj.product_set.all()[0]
# ↑ Here
print(product_obj.id, product_obj.name, product_obj.price)
Output:
1 Apple 10.00
But, you cannot access the parent model Category
from the child model Product
with _set
as shown below:
product_obj = Product.objects.all()[0]
category_obj = product_obj.category_set.all()[0]
# ↑ Cannot access "Category" with "_set"
print(category_obj.id, category_obj.name)
Then, the error below occurs:
AttributeError: ‘Product’ object has no attribute ‘category_set’
But, you can access the parent model Category
with the foreign key field category
in the child model Product
as shown below:
product_obj = Product.objects.all()[0]
category_obj = product_obj.category
# ↑ Here
print(category_obj.id, category_obj.name)
Output:
1 Fruits
- [Django]-Python + Django page redirect
- [Django]-How to chcek if a variable is "False" in Django templates?
- [Django]-How to mock users and requests in django