英文:
Django Admin select_related issue
问题
I'm trying to select_related
for a bunch of assets in the Django admin.
These assets are tied to a product, which in turn has a separate Company and Category model. These are both a foreign key from the product to the respective model.
I defined the string method like so in the Product class:
def __str__(self):
if self.company:
return f"{self.category.name} | {self.company.name} | {self.name}"
return f"{self.category.name} | {self.name}"
However, when I check the debug toolbar in the Django admin, I see that a bunch of extra queries are made because of this.
products\models.py in __str__(53)
return f"{self.category.name} | {self.company.name} | {self.name}"
I have the following get_queryset
method defined in the ModelAdmin:
def get_queryset(self, request):
qs = super().get_queryset(request).select_related(
'product',
'product__category',
'product__company')
if request.user.is_superuser or request user.is_staff:
return qs
return qs.filter(user=request.user)
Is there a fix for this? Am I doing it wrong?
Edit*
I have narrowed down the issue to Django admin's list filter.
The list_filter
allows filtering by product, which in turn displays its __str__
method.
I have decided to just remove the product from the list filter.
Would still be nice to have a fix provided for any future visitors.
英文:
I'm trying to select_related
for a bunch of assets in the Django admin.
These assets are tied to a product, which in turn has a separate Company and Category model. These are both a foreign key from product, to the respective model.
I defined the string method like so in the Product class:
def __str__(self):
if self.company:
return f"{self.category.name} | {self.company.name} | {self.name}"
return f"{self.category.name} | {self.name}"
However, when I check debug toolbar in the Django admin, I see that a bunch of extra queries are made because of this.
products\models.py in __str__(53)
return f"{self.category.name} | {self.company.name} | {self.name}"
I have the following get_queryset
method defined in the ModelAdmin:
def get_queryset(self, request):
qs = super().get_queryset(request).select_related(
'product',
'product__category',
'product__company')
if request.user.is_superuser or request.user.is_staff:
return qs
return qs.filter(user=request.user)
Is there a fix for this? Am I doing it wrong?
Edit*
I have narrowed down the issue to Django admin's list filter.
The list_filter
allows filtering by product, which in turn displays it's __str__
method.
I have decided to just remove the product from the list filter.
Would still be nice to have a fix provided for any future visitors.
答案1
得分: 1
你可以使用 prefetch_related
替代 select_related
,因为它比 select_related
更灵活,可以用来预取任何深度级别的相关字段,如下所示:
def get_queryset(self, request):
qs = super().get_queryset(request).prefetch_related(
'product',
'product__category',
'product__company')
if request.user.is_superuser or request.user.is_staff:
return qs
return qs.filter(user=request.user)
英文:
You can use prefetch_related
instead of select_related
as it is more versatile than select_related
and can be used to prefetch related fields at any level of depth so:
def get_queryset(self, request):
qs = super().get_queryset(request).prefetch_related(
'product',
'product__category',
'product__company')
if request.user.is_superuser or request.user.is_staff:
return qs
return qs.filter(user=request.user)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论