Eine meiner Django-Websites verfügt über folgende Datenbankmodelle: In der Django-App "common":

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)

In der Django App "Sitcom":

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)

Kurz gesagt, die Modellklasse Relation verfügt über 3 Fremdschlüssel für andere Tabellen. Das Problem ist, wenn ich Django Admin verwende, um eine einzelne Beziehung zu ändern, wird die Seite (change_form) ziemlich langsam geladen. Später habe ich die Modellklassenbeziehung wie folgt geändert:

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)

Durch die Änderung wurden Fremdschlüssel in IntegerFields geändert, sodass einige der Magien im Django ORM-System deaktiviert wurden. Jetzt wird die Seite zum Ändern des Formulars sehr schnell geladen. Meine Frage ist, was ist die "behinderte Magie in Django Orm"? Was kann das Problem verursachen?

12
Brent81 26 Mai 2013 im 05:05

5 Antworten

Beste Antwort

Es ist nicht die Magie von Django Orm. Es ist Magie der Form. Wenn Sie einen Fremdschlüssel in Model und dann in ModelForm erstellen, wird ein ModelChoiceField erstellt, das alle Auswahlmöglichkeiten für ForeignKey Model bietet. Und django Admin verwendet alle Eigenschaften von Form, um HTML zu erstellen. Verwenden Sie also diesen Code.

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 

In der Admis-Site

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

Sie können die übergebenen Auswahlmöglichkeiten auch in einem Formular zwischenspeichern.

12
Brent81 27 Mai 2013 im 09:05

In meinem Fall wurde die Langsamkeit hauptsächlich durch das veraltete django-debug-toolbar (v1.7) verursacht. debug_toolbar.middleware.DebugToolbarMiddleware würde dazu führen, dass das Laden der Administrationsseite buchstäblich 20 Minuten dauert, wenn sie ein ForeignKey-Feld mit ein paar hundert Auswahlmöglichkeiten enthält. Ein Upgrade der Symbolleiste auf Version 1.8 hat alles gelöst. Vielleicht hilft das jemandem.

1
serg 21 Okt. 2017 im 18:11

Wenn ein ForeignKey-Modell zu viele Datensätze enthält, wird Ihr Bearbeitungsformular möglicherweise eingefroren. Der beste Weg, um zu beginnen, besteht darin, die Felder zu begrenzen, die im Formular angezeigt werden sollen, und nach und nach / nacheinander weitere Felder hinzuzufügen, um zu überprüfen, welches Feld das Formular verlangsamt.

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

Nach dem Hinzufügen eines Feldes, das das Problem verursacht, z. Medien würde das Formular wieder einfrieren. Wenn Sie dieses Feld im Formular weiterhin benötigen, können Sie die Antwort von Vishal Shah mit raw_id_fields = ('Media',) verwenden.

0
Kostyantyn 1 Sept. 2015 im 16:18

Ich bin bereit zu wetten, dass das Problem an Ihrem ForeignKey liegt. Standardmäßig rendert django für jeden Fremdschlüssel ein <select> -Element.

Wenn Sie Tausende von Zeilen haben, wird Ihr HTML / DOM dadurch leicht aufgebläht, und ich habe festgestellt, dass Browser bei 20.000 Elementen, die in einem <select> -Tag gerendert wurden, anfangen zu scheißen.

Um dies zu beheben, sollten Sie Ihr Administratorformular überschreiben und nicht die Standard-Widgets verwenden.

8
Yuji 'Tomita' Tomita 26 Mai 2013 im 05:32

In admin.py.

from django.contrib import admin

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

admin.site.register(Relation, RelationAdmin)

Dies bringt ein nettes kleines UI-Element in das Formular und verbessert die Leistung erheblich, da nicht viele Optionen in das Auswahlfeld geladen werden müssen.

22
Vishal Shah 26 Nov. 2013 im 12:01