gpt4 book ai didi

django - 在 Django Admin 中使用 raw_id_fields 时如何优化查询数量

转载 作者:行者123 更新时间:2023-12-02 00:03:05 32 4
gpt4 key购买 nike

我有一个数据模型如下:

class Candidate(models.Model):
name = models.CharField()

class Skill(models.Model):
name = models.CharField()

class CandidateSkill(models.Model):
candidate = models.ForeignKey(Candidate)
skill = models.ForeignKey(Skill, related_name='candidate_skills')
proficiency = models.CharField()

在管理员中我有:

class CandidateSkillInline(admin.TabularInline):
model = CandidateSkill
fields = ('skill', )
extra = 0
raw_id_fields = ('skill',)

class CandidateAdmin(admin.ModelAdmin):
model = Candidate
fields = ('name',)
inlines = [CandidateSkillInline]

每个候选人都可以拥有多种技能。这里的问题是,在每个内联的更改页面中,将使用一个查询来获取技能( SELECT ••• FROM "skill" WHERE "skill"."id" = <id> )。如果我添加字段 skillCandidateSkillInlineread_only那么就不会有额外的查询。不过,我希望能够在内联中添加新项目。我尝试过的事情:

1) 将自定义表单集添加到 CandidateSkillInline :

class CandidateSkillInlineFormset(BaseInlineFormSet):
def __init__(self, *args, **kwargs):
super(CandidateSkillInlineFormset, self).__init__(*args, **kwargs)
self.queryset = self.queryset.select_related('skill')

2) 覆盖get_queryset在内联上:

def get_queryset(self, request):
super(CandidateSkillInline, self).get_queryset(request).select_related('skill')

3) 覆盖get_querysetCandidateAdmin :

def get_queryset(self, request):
return super(CandidateAdmin, self).get_queryset(request).prefetch_related('candidate_skills__skill')

但是,我仍然收到针对每项技能的查询。不发送查询的唯一方法是当我设置 skill 时在read_only_fields在 CandidateSkillInilne 中。问题是如何在一个查询中选择或预取技能,而不是为每个内联选择或预取技能?

最佳答案

嗯,ForeignKeyRawIdWidget的设计并不是那么优雅。 ForeignKeyRawIdWidget 不只是以特定方式显示一些数据(这是小部件的基本职责),而是进行额外的查询以在屏幕上显示更多相关信息(它显示 >str(obj) 方法)。

查询在label_and_url_for_value方法中执行。因此,您可以尝试使用自己的自定义小部件来避免此查询,但您必须考虑可视化中的权衡。

一种可能的解决方案:

from django.contrib.admin.widgets import ForeignKeyRawIdWidget
from django.urls import reverse

class OptimisedForeignKeyRawIdWidget(ForeignKeyRawIdWidget):
def label_and_url_for_value(self, value):
try:
url = reverse(
'%s:%s_%s_change' % (
self.admin_site.name,
self.rel.model._meta.app_label,
self.rel.model._meta.object_name.lower(),
),
args=(value,)
)
except NoReverseMatch:
url = '' # Admin not registered for target model.
return str(value), url

最后一步,您必须在 ModelForm 类中设置自定义小部件。有很多方法可以做到这一点。

关于django - 在 Django Admin 中使用 raw_id_fields 时如何优化查询数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40888175/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com