我有一个如下的数据模型:
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>)。如果我在CandidateSkillInline中将字段skill添加为read_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)覆盖CandidateAdmin上的get_queryset
def get_queryset(self, request):
return super(CandidateAdmin, self).get_queryset(request).prefetch_related('candidate_skills__skill')但是,我仍然会得到每个技能的查询。不发送查询的唯一方法是在CandidateSkillInilne的read_only_fields中设置skill。问题是,我如何在一个查询中选择或预取技能,而不是每个内联查询一个技能?
发布于 2016-11-30 20:28:10
这看起来像是你在尝试实现你自己的ManyToManyField。你能用ManyToManyField和内联来代替吗?它在管理中有一个很好的多选小部件。
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#working-with-many-to-many-models
发布于 2019-12-17 04:38:52
嗯,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类中设置自定义小部件。有很多方法可以做到这一点。
https://stackoverflow.com/questions/40888175
复制相似问题