2015-04-15 2 views
5

Использование Django 1.8 на Python 3.4.1 с моделями:Django администратора рядный: select_related

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 делает Django выполнить запрос для таблицы Product. Все эти методы упоминались в stackoverflow, но они обрабатывали ModelAdmin и не помогали с Inline. Что мне не хватает?

ответ

1

В настоящее время я работаю над аналогичной проблемой. То, что я нашел, задокументировано в этой теме: Translatable Manytomany fields in admin generate many queries

Одним из важных замечаний я сделал то, что мое решение работает только для Django 1.7x, а не для 1.8. Точно такой же код, с d1.7 У меня порядок 10^1 запросов, а с новой установкой d1.8 у меня 10^4.

решения
3

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 класс фильтрует QuerySet для вас, и вы должны принять, что отфильтрованный QuerySet и добавить предвыборку. С помощью вашей реализации набора форм (набор запросов all()) вы получаете несвязанные объекты ComingProduct и, вероятно, слишком много времени для рендеринга. Когда это отфильтрованный запрос, он отображается очень быстро.

+0

Ох. это спасатель жизни. У меня была модель A, в которой было много встроенных моделей модели B. B имел три m2m и два fk отношения. более того. был использован перевод модели. Кроме того, Граппелли с его автозаполнением помог. – Aitvaras

+0

К сожалению, он не работает в Django 2.0 – ramusus

+0

Как это сделать? Не похоже, что соответствующий код Django изменился – noamk

Смежные вопросы