[Django] ein Problem mit "models.ForeignKey"

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
snoer
User
Beiträge: 29
Registriert: Montag 2. Juni 2008, 18:13

Hallo

Ich möchte eine Plattform schreiben auf der man verschiedene Dinge veröffentlichen kann.
Diese Dinge können ein Text, ein Bild, eine Datei, oder auch alles auf einmal sein.
Man hat Also ein Formular mit einem Textfeld, einem Filefield und einem Imagefield.
Jeder soll auf jeden Eintrag reagieren können, ähnlich wie in einem Usenetforum, oder auch
einen komplett neuen Beitrag ohne Bezug erstellen können.Auch diese Beiträge sollen Text, Bild, Datei oder alles auf einmal sein.

Also habe ich eine Klasse definiert die ich Objekt genannt habe.

Code: Alles auswählen

class Objekt (models.Model):
	titel = models.CharField('Titel', max_length = 100)
	nachricht = models.TextField('Nachricht', blank = True)
	datei = models.FileField('Datei', upload_to = '/media/ups/', blank = True)
	bild = models.ImageField('Bild', upload_to = '/media/ups/', blank = True)
	autor = models.CharField('Autor', max_length = 25)
	datum = models.CharField(max_length = 10)
	c_datum = models.CharField(max_length = 10)
	bezug = models.ForeignKey(Objekt, blank = True)

Jetzt meckert Django beim syncdb natürlich, dass die Klasse "Objekt" nicht definiert ist.
(letzte Zeile im Codeblock)
Wie kann ich dieses Problem umgehen ohne die verschiedenen Beiträge unterschiedlich zu klassifizieren?

Ich hoffe mein Problem ist klar geworden.

schöjn Gruß
snoer
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Schau doch mal in die Dokumentation, dort wird exakt beschrieben, wie man Relations zum gleichen Objekt machen soll.
snoer
User
Beiträge: 29
Registriert: Montag 2. Juni 2008, 18:13

oh..
okay werd ich machen, danke.
für ähnlich weit denkende die diesen thread auf der suche nach antwort lesen

Code: Alles auswählen

	bezug = models.ForeignKey('self', blank = True)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Noch ein paar Anmerkungen: `Objekt` scheint mir ein zu generischer Name zu sein. Von deutschen Namen würde ich persönlich sowieso Abstand nehmen, denn sie wirken fremd und erst ab Python 3.x (mit dem Django nicht funktioniert) kann man korrekte deutsche Namen mit Umlauten verwenden.

Etwas wie `datei` und `bild` würde ich jeweils als eigene Objekte modellieren, denn schnell gibt es hier den Wunsch nach weiteren Metadaten, etwa der Dimension eines Bildes. `author` sollte auch auf ein Modell verweisen und nicht nur ein String sein. Die beiden Datumse schließlich sollte `DateTimeField`s seinen.

Die Baumstruktur, die du ja mit dem Selbstbezug modellierst, würde ich durch einen eigenen `Manager` noch expliziter machen. Vielleicht so (gibt es bestimmt schon irgendwo noch besser, aber dieses hier ist nach Rails' `act_as_tree`-Plugin modelliert):

Code: Alles auswählen

class HierarchicalManager(models.Manager):
    @property
    def root(self):
        return self.get(parent__isnull=True)

    @property
    def roots(self):
        return self.filter(parent__isnull=True)

class HierarchicalModel(models.Model):
    objects = HierarchicalManager()

    parent = models.ForeignKey('self', related_name='children', null=True)

    def ancestors(self):
        node, nodes = self, []
        while node.parent:
            node = node.parent
            nodes.append(node)
        return nodes
    
    def root(self):
        return self.ancestors()[-1]

    def siblings(self, including_self=False):
        nodes = (self.parent.children if self.parent else self.objects.roots).all()
        if not including_self: 
            nodes = nodes.exclude(pk=self.pk)
        return nodes
Achtung: `ancestors` und das darauf basierende `root` sind sehr ineffizient, da Djangos ORM kein Caching kennt. Dafür ist's einfach und wenn er's mal kennt, wird's auch effizienter. Wenn man's für Breadcrumbs o.ä. nutzt, sollte man diese auf View-Ebene cachen.

Was fällt mir noch ein: Ich würde die Kinder noch anordnen, etwa durch eine Spalte `position`. Dann muss man noch ein `ordering` in einer `Meta`-Klasse definieren. Dieses sollte automatisch von den Relation-Managern aufgepickt werden. Das Einfügen und Verschieben von Elementen wird jetzt aber aufwendiger. Ein paar Anregungen kann man sich bei Rails' `acts_as_list` holen.

Stefan
Antworten