2015-04-15 31 views
5

Korzystanie Django 1.8 na Python 3.4.1 z modelami:Django Admin inline: 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 

oraz następujące admin.py:

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


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

Oczywiście, mam problem z zapytaniami pomnożyć do bazy danych: mam zapytanie dla każdego elementu na liście i zapytanie dla każdej linii. Tak więc, mając 100 pozycji, otrzymuję 100^2 zapytań. Rozwiązałem problem z zapytaniami dla każdej linii z Caching queryset choices for ModelChoiceField or ModelMultipleChoiceField in a Django form Ale nadal mam problem z metodą str. Próbowałem następujące:

1) dodanie prefetch_related do ComingAdmin:

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

2) dodanie select_related do ComingProductInline:

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

3) Definiowanie niestandardowego formularza inline i dodając do select_related zestaw zapytań w polu:

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) Definiowanie niestandardowego zestawu formularzy:

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) Różne kombinacje poprzednich 4 metod

i nic nie pomaga: każde wezwanie str dla PricedProduct sprawia Django wykonać kwerendy dla tabeli produktów. Wszystkie te metody zostały wymienione na stackoverflow, ale traktowały ModelAdmin i nie pomagają w Inline. Czego mi brakuje?

Odpowiedz

1

Pracuję obecnie nad podobnym problemem. To, co znalazłem jest udokumentowane w tym wątku: Translatable Manytomany fields in admin generate many queries

Jedną z ważnych obserwacji, którą zrobiłem, było to, że moje rozwiązanie działa tylko dla Django 1.7x, a nie dla 1.8. Dokładnie ten sam kod, z d1.7 mam porządek 10^1 zapytań, a przy nowej instalacji d1.8 mam 10^4.

rozwiązanie
3

formset działa dla mnie, ale z nieco innego podejścia:

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

klasie BaseInlineFormSet filtruje queryset dla ciebie, i trzeba wziąć to przefiltrowane queryset i dodać prefetch. Przy użyciu implementacji zestawu formularzy (zestawu zapytań all() uzyskuje się niepowiązane obiekty ComingProduct, a renderowanie zajmuje prawdopodobnie zbyt wiele czasu. Gdy jest to przefiltrowany zestaw zapytań, renderuje się bardzo szybko.

+0

Och. to jest ratownik. Miałem model A, który miał wiele rzędów modelu B. B miał trzy m 2m i dwa fk relacje. co więcej. zastosowano tłumaczenie modelu. Pomógł także Grappelli z funkcją autouzupełniania. – Aitvaras

+0

Niestety, to nie działa w Django 2.0 – ramusus

+0

Jak to zrobić? Wygląda na to, że odpowiedni kod Django się nie zmienił – noamk