2013-05-26 14 views
6

Jeden z moich witryn Django ma następujące modele baz danych: W Django App „wspólny”:Django Admin zmiana obciążenia forma dość powolna

class Collection(models.Model): 
    name = models.CharField(max_length = 255, unique = True) 
    _short_name = models.CharField(db_column="short_name", max_length = 32, blank=True) 

class Particle(models.Model): 
    content = models.TextField(blank=False) 
    owner = models.ForeignKey(Collection) 
    order = models.IntegerField(null=True, blank=True) 

W Django App „sitcomie”:

class Media(models.Model): 
    name = models.CharField(max_length = 248) 
    _short_name = models.CharField(db_column="short_name", max_length = 32, blank=True) 
    capital = models.CharField(max_length = 1) 
    description = models.TextField(blank=True) 
    progress = models.CharField(max_length = 32, blank=True, null=True) 

class Relation(models.Model): 
    name = models.CharField(max_length = 128) 
    _short_name = models.CharField(db_column="short_name", max_length = 32, blank=True) 
    description = models.TextField(blank=True) 
    parent = models.ForeignKey('self', blank=True, null=True) 
    order = models.IntegerField(blank=True, null=True) 
    particle = models.ForeignKey(Particle, blank=True, null=True) 
    media = models.ForeignKey(Media, blank=True, null=True) 

W short, model class Relation ma 3 klucze obce dla innych tabel. Problem polega na tym, że gdy używam Administratora Django do zmiany pojedynczej relacji, strona (change_form) ładuje się dość wolno. Później zmieniłem modelu klasy Relacja następująco:

class Relation(models.Model): 
    name = models.CharField(max_length = 128) 
    _short_name = models.CharField(db_column="short_name", max_length = 32, blank=True) 
    description = models.TextField(blank=True) 
    order = models.IntegerField(blank=True, null=True) 
    parent_id = models.IntegerField(blank=True, null=True) 
    particle_id = models.IntegerField(blank=True, null=True) 
    media_id = models.IntegerField(blank=True, null=True) 

Modyfikacja zmieniła klucze obce do IntegerFields, więc wyłączył niektóre magii wewnątrz systemu Django ORM, a teraz formie zmiana strona ładuje się bardzo szybko. Moje pytanie brzmi, jaka jest "wyłączona magia wewnątrz django orm"? co może spowodować problem?

Odpowiedz

9

To nie jest magia django Orm. To magia formy. Po utworzeniu klucza obcego w Modelu, a następnie w ModelForm, tworzona jest funkcja ModelChoiceField, która ma wszystkie opcje modelu klucza obcego. Administrator django wykorzystuje wszystkie właściwości formularza do tworzenia HTML. Więc użyj tego kodu.

from django import forms 
class RelationForm(forms.ModelForm): 
    parent = forms.ChoiceField(required=False, 
           choices=Relation.objects.values_list('id', 'name')) 
    particle = forms.ChoiceField(required=False, 
           choices=Particle.objects.values_list('id', 'content')) 
    media = forms.ChoiceField(required=False, 
           choices=Media.objects.values_list('id', 'name')) 

    class Meta: 
     model = Relation 

W Admis Site

from django.contrib import admin 
class RelationAdmin(admin.ModelAdmin): 
    form = RelationForm 
    model = Relation 

Można także buforować wybory przekazać w formie.

+0

dziękuję bardzo! to działa, a teraz mogę ponownie użyć ForeignKey, to znacznie więcej wygody. – Brent81

3

Zgadzam się, że problem jest spowodowany twoją ForeignKey. Domyślnie django renderuje element <select> dla każdego klucza obcego.

Jeśli masz tysiące wierszy, to z łatwością zaczniesz nadużywać HTML/DOM i zauważyłem, że przeglądarki zaczynają się marudzić przy 20 000 elementach renderowanych w tagu <select>.

Aby to naprawić, spójrz na przesłonięcie formularza administratora i nie używaj domyślnych widgetów.

12

W admin.py

from django.contrib import admin 

class RelationAdmin(admin.ModelAdmin): 
     raw_id_fields = ('Media','Particle',) 

admin.site.register(Relation, RelationAdmin) 

Pojawi się miłą elementu UI w formie i znacznie poprawia wydajność, ponieważ nie trzeba załadować ogromną liczbę opcji w polu wyboru.

+1

Dzięki! Ta mała wskazówka sprawia, że ​​moja strona administratora jest o wiele bardziej użyteczna! – yairchu

+1

Czasami nie chcesz edytować pól w formularzach administracyjnych, po prostu je przeglądaj, możesz również dodać 'readonly_fields = ('Media', 'Particle',)' –

0

Jeśli model klucza obcego ma zbyt wiele rekordów, może zablokować formularz edycji. Najlepszym sposobem na rozpoczęcie jest ograniczenie pól, które powinny być wyświetlane w formularzu i stopniowo/jedno po drugim, dodawanie innych pól, sprawdzanie, które pole powoduje powolne działanie formularza.

from django.contrib import admin 
class RelationAdmin(admin.ModelAdmin): 
     fields = ('name',) 
admin.site.register(Relation, RelationAdmin) 

Następnie po dodaniu pola powodującego problem, np. Media, forma znowu zamarznie. Dlatego jeśli nadal potrzebujesz tego pola w formularzu, możesz użyć odpowiedzi Vishala Shaha z raw_id_fields = ("Media",)

0

W moim przypadku spowolnienie spowodowane było głównie przez nieaktualne django-debug-toolbar (v1.7). debug_toolbar.middleware.DebugToolbarMiddleware spowodowałoby, że strona administratora dosłownie zajęłaby 20 minut, gdyby zawierała pole ForeignKey z kilkoma setkami opcji. Aktualizacja paska narzędzi do wersji 1.8 rozwiązała wszystko.Może to pomaga komuś.