在Python 3.4.1上使用带有模型的Django 1.8:
class Product(models.Model):
name = models.CharField(max_length=255)
# some more fields here
def __str__(self):
return self.name
class PricedProduct(models.Model):
product = models.ForeignKey(Product, related_name='prices')
# some more fields here
def __str__(self):
return str(self.product)
class Coming(models.Model):
# some unimportant fields here
class ComingProducts(models.Model):
coming = models.ForeignKey(Coming)
priced_product = models.ForeignKey(PricedProduct)
# more unimportant fields
和以下admin.py:
class ComingProductsInline(ForeignKeyCacheMixin, admin.TabularInline):
model = ComingProducts
class ComingAdmin(admin.ModelAdmin):
inlines = [ComingProductsInline]
当然,我遇到了对数据库进行多次查询的问题:我对列表中的每个项目进行查询,并对每一行进行查询 . 所以,有100个项目,我得到100 ^ 2个查询 . 我用Caching queryset choices for ModelChoiceField or ModelMultipleChoiceField in a Django form解决了每行查询的问题但是我仍然遇到 str 方法的问题 . 我尝试过以下方法:
1)将prefetch_related添加到ComingAdmin:
def get_queryset(self, request):
return super(ComingAdmin, self).get_queryset(request). \
prefetch_related('products__product')
2)将select_related添加到ComingProductInline:
def get_queryset(self, request):
return super(ComingProductsInline, self).get_queryset(request). \
select_related('priced_product__product')
3)为内联定义自定义表单并将select_related添加到字段查询集:
class ComingProductsInline(ForeignKeyCacheMixin, admin.TabularInline):
model = ComingProducts
form = ComingProductsAdminForm
class ComingProductsAdminForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ComingProductsAdminForm, self).__init__(args, kwargs)
self.fields['priced_product'].queryset = PricedProduct.objects.all(). \
select_related('product')
class Meta:
model = ComingProducts
fields = '__all__'
4)定义自定义formset:
class ComingProductsInline(ForeignKeyCacheMixin, admin.TabularInline):
model = ComingProducts
formset = MyInlineFormset
class MyInlineFormset(BaseInlineFormSet):
def __init__(self, data=None, files=None, instance=None,
save_as_new=False, prefix=None, queryset=None, **kwargs):
super(MyInlineFormset, self).__init__(data, files, instance,
save_as_new, prefix, queryset, **kwargs)
self.queryset = ComingProducts.objects.all(). \
prefetch_related('priced_product__product')
5)前4种方法的不同组合
并没有什么帮助:每次调用PricedProduct的str都会让Django对Product表执行查询 . 所有这些方法都在stackoverflow上提到,但是他们对ModelAdmin进行了处理,并且对Inline没有帮助 . 我错过了什么?
3 回答
我目前正在处理类似的问题 . 我发现的内容记录在这个帖子中:Translatable Manytomany fields in admin generate many queries
我做的一个重要观察是我的解决方案仅适用于Django 1.7x而不适用于1.8 . 完全相同的代码,与d1.7我有10 ^ 1的查询顺序,而新安装的d1.8我有10 ^ 4 .
formset解决方案对我有用,但方法略有不同:
BaseInlineFormSet类为您过滤查询集,您需要获取该过滤的查询集并添加预取 . 使用formset实现(all()查询集),您将获得无关的ComingProduct对象,渲染可能需要很长时间 . 当它是过滤后的查询集时,它会很快呈现 .
你会发现这种方法非常有用:
project/admin.py
app/admin.py
我所要做的就是定义select_related字段,Custom
AdminWithSelectRelated
,AdminInlineWithSelectRelated
和FilterWithSelectRelated
将它们用于Changelists,Changeforms甚至内联Formset .奇迹般有效 .