python - Django 管理员内联 : select_related

标签 python django foreign-keys admin django-queryset

在带有模型的 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) 定义自定义表单集:

 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,对内联没有帮助。我想念什么?

最佳答案

formset 解决方案对我有用,但方法略有不同:

class MyInlineFormset(BaseInlineFormSet):
    def __init__(self, *args, **kwargs):
        super(MyInlineFormset, self).__init__(*args, **kwargs)
        self.queryset = self.queryset.prefetch_related('priced_product__product')

BaseInlineFormSet 类为您过滤查询集,您需要获取过滤后的查询集并添加预取。使用您的表单集实现(all() 查询集),您会得到不相关的 ComingProduct 对象,并且可能需要很长时间才能呈现。当它是过滤查询集时,它会非常快速地呈现。

关于python - Django 管理员内联 : select_related,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29647418/

相关文章:

Python 文件重命名

Python 子进程将调用输出存储到文件

Python正则表达式将字符串拆分为数字和文本/符号

python - 为数据库中现有条目生成 slug 字段数据

python - 在 Django 中验证 Google ID token

php - 使用 CakePHP 将记录插入数据库会导致外键冲突

python - 更新主键 Django MySQL

SQL - 在具有不同列数的多列上创建外键

python - SqlAlchemy - 按关系属性过滤

javascript - 包裹 html 标签以使所有标签都可点击