Django admin inline:select_related [英] Django admin inline: select_related

查看:214
本文介绍了Django admin inline:select_related的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  class Product(models.Model):
name = models.CharField(max_length = 255)
#这里还有一些字段

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):
inline = [ComingProductsInline]

当然,我对数据库的乘法查询有问题:我有列表中的每个项目的查询和每行的查询。所以,有100项我得到100 ^ 2查询。
我已经使用为Django表单中的ModelChoiceField或ModelMultipleChoiceField缓存查询选项
但是我仍然遇到 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:

$ b

  def get_queryset(self,request):
return super(ComingProductsInline,self).get_queryset(request)。 \
select_related('priced_product__product')

3)定义内联和添加的自定义表单select_related to field queryset:

  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,文件=无,实例=无,
save_as_new = False,前缀=无,queryset =无,** kwargs):
super(MyInlineFormset,self).__ init __(数据,文件,实例,
save_as_new,前缀,queryset,** kwargs)
self.queryset = ComingProducts.objects.all()。 \
prefetch_related('priced_product__product')

5)以前4种方法的不同组合



没有任何帮助:每个调用PricedProduct的str使Django对Product表执行查询。所有这些方法都在stackoverflow中提到,但他们处理了ModelAdmin,并且不帮助Inline。我想念什么?

解决方案

表单解决方案对我来说是有效的,但是有一个稍微不同的方法:

  class MyInlineFormset(BaseInlineFormSet):
def __init __(self,* args,** kwargs):
super(MyInlineFormset,自我).__ init __(* args,** kwargs)
self.queryset = self.queryset.prefetch_related('priced_product__product')

BaseInlineFormSet类为您过滤查询集,您需要使用该过滤的查询集并添加预取。使用您的formset实现(all()queryset),您可以获得无关的ComingProduct对象,并且渲染可能需要太长时间。当它是过滤的查询器,它很快呈现。


Using Django 1.8 on Python 3.4.1 with models:

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

and the following admin.py:

class ComingProductsInline(ForeignKeyCacheMixin, admin.TabularInline):
    model = ComingProducts


class ComingAdmin(admin.ModelAdmin):
    inlines = [ComingProductsInline]

Of course, i have a problem with multiply queries to database: i have a query for each item in list and a query for each line. So, having 100 items i get 100 ^ 2 queries. I've solved the problem with queries for each line with Caching queryset choices for ModelChoiceField or ModelMultipleChoiceField in a Django form But i still having problem with str method. I've tried the following:

1) adding prefetch_related to ComingAdmin:

def get_queryset(self, request):
    return super(ComingAdmin, self).get_queryset(request). \
    prefetch_related('products__product')

2) adding select_related to ComingProductInline:

def get_queryset(self, request):
    return super(ComingProductsInline, self).get_queryset(request). \
    select_related('priced_product__product')

3) Defining custom form for inline and adding select_related to field queryset:

 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) Defining a custom 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) Different combinations for previous 4 methods

And nothing helps: each call of str for PricedProduct makes Django to perform a query for Product table. All of these methods were mentioned on stackoverflow, but they treated ModelAdmin, and do not help with Inline. What do i miss?

解决方案

The formset solution does work for me, but with a slightly different approach:

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

The BaseInlineFormSet class filters the queryset for you, and you need to take that filtered queryset and add the prefetch. With your formset implementation (the all() queryset) you get unrelated ComingProduct objects and it probably takes much too long to render. When it's the filtered queryset it renders very quickly.

这篇关于Django admin inline:select_related的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆