-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question about PrimaryKeyRelatedField with many=True
#9607
Comments
Are you prefeching the relationship in your view? You'll need to use Django's |
This is for validation purposes, so I cannot use def put(self, request):
serializer = MachinePartUpdateSerializer(data=request.data)
serializer.is_valid() Here is the serializer: class MachinePartSerializer(ModelSerializer):
brand = PrimaryKeyRelatedField(
pk_field=IntegerField(),
queryset=MachineBrand.objects.filter(active=True),
required=True,
)
# TODO: performance issue n+1
model = PrimaryKeyRelatedField(
pk_field=IntegerField(),
queryset=MachineModel.objects.filter(active=True),
many=True,
required=True,
)
class Meta:
model = MachinePart
fields = ["id", "brand", "model", "name", "description"] Here is my model using a many-to-many relationship: class MachinePart(Model):
brand = ForeignKey(MachineBrand, on_delete=models.CASCADE)
model = ManyToManyField(MachineModel, related_name="parts")
name = CharField(max_length=255)
part_number = CharField(max_length=255)
description = TextField(blank=True, null=True)
active = BooleanField(default=True) So, how should I handle prefetch the relations |
Ah ok, I thought you were doing a read-only request, I didn't realise it was a PUT request. I don't know the answer in this case. |
This might be a bug. It seems that the case of |
The problem lies in the implementation of This is not technically a bug, because it does what it is expected, yet it is a bad usage of resources and should be addressed. |
Maybe this could open a PR to optimize it. |
The behavior you're observing is due to how Django's PrimaryKeyRelatedField interacts with the database when many=True is used. Each item in the list of primary keys results in an individual query to fetch the corresponding MachineModel instance. This can lead to N+1 query problems, where N is the number of related objects being fetched. PrimaryKeyRelatedField : |
So, is there no solution for this issue? |
This may be handled like it is done in Django core MultipleChoiceField: build a "bulk" select and than check if every provided key is in the returned queryset: This is not an hard task, since an implementation is ready for use for the same use-case. |
We hit this today. Searching the repo I see an attempt was made a while back:
And there's also a approach suggested here: #8919 (comment) which is to try a single [
self.child_relation.to_internal_value(item)
for item in data
] |
I have some questions regarding the following code snippet:
When
PrimaryKeyRelatedField
is set withmany=True
, it generates these queries. It seems like they are not using join.Is this behavior a bug, or is it expected not to use join?
The text was updated successfully, but these errors were encountered: