Django-Anfängerfrage: Logik in Model/Views/...?

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
cuthbert
User
Beiträge: 5
Registriert: Samstag 11. August 2007, 14:43

Hallo zusammen!

Ich blicke schon seit längerem ab und zu auf Django und komme jetzt auch erstmal dazu, es auch wirklich zu testen.
Als erstes Beispielprojekt wollte ich eine kleine Ligaverwaltung für eine private bzw. regionale Sportliga erstellen.
Model ist fertig, Eintragen über's Admin-Interface auch kein Problem, die URLs sind auch in Ordnung, nun hänge ich doch ein wenig bei den Views. Und dabei stellt sich mir dann die grundsätzliche Frage: Wo baue ich die Logik für die Views ein? In den Views selber, oder auch im Model?
Konkret geht es darum, dass ich erst einmal nur die Tabelle der Liga ausgeben möchte (mit Punkten und Toren/Gegentoren).
Rein aus DB-Sicht würde ich mir dafür wahrscheinlich einen DB-View bauen, auf den ich dann zugreifen könnte.
Wie ist bei Django die empfohlene Vorgehensweise für sowas?

Ich freue mich auf Anregungen und Kritik!
cuthbert

Meine Models sehen wie folgt aus (ein wenig gekürzt):

Code: Alles auswählen

class Verein(models.Model):
    name = models.CharField(max_length=100)
    link = models.URLField(verify_exists=True, max_length=200, blank=True)

    class Meta:
        verbose_name_plural = 'Vereine'

    def __unicode__(self):
        return self.name

class Spieltag(models.Model):
    nummer = models.IntegerField()

    class Meta:
        verbose_name_plural = 'Spieltage'

    def __unicode__(self):
        return '%s. Spieltag' % self.nummer

class Schiedsrichter(models.Model):
    name = models.CharField(max_length=100)

    class Meta:
        verbose_name_plural = 'Schiedsrichter'

    def __unicode__(self):
        return self.name

class Spielort(models.Model):
    bezeichnung = models.CharField(max_length=200)
    adresse = models.CharField(max_length=200)
    plz = models.CharField(max_length=5)
    ort = models.CharField(max_length=100)
    map24_link = models.URLField(verify_exists=True, max_length=300)

    class Meta:
        verbose_name_plural = 'Spielorte'

    def __unicode__(self):
        return self.bezeichnung

class Spiel(models.Model):
    spieltag = models.ForeignKey('Spieltag')
    verein_heim = models.ForeignKey('Verein', related_name='Heimteam')
    verein_gast = models.ForeignKey('Verein', related_name='Gastteam')
    spielort = models.ForeignKey('Spielort')
    datum_zeit = models.DateTimeField(auto_now=False, auto_now_add=False)
    schiedsrichter1 = models.ForeignKey('Schiedsrichter', related_name='Schiedsrichter 1', blank=True)
    schiedsrichter2 = models.ForeignKey('Schiedsrichter', related_name='Schiedsrichter 2', blank=True)
    gespielt = models.BooleanField()
    tore_heim_gesamt = models.IntegerField(blank=True,null=True)
    tore_gast_gesamt = models.IntegerField(blank=True,null=True)

    class Meta:
        verbose_name_plural = 'Spiele'

    def __unicode__(self):
        return '%s vs. %s (%s)' % (self.verein_heim.name, self.verein_gast.name, self.datum_zeit)

    def paarung(self):
        return '%s vs. %s (%s)' % (self.verein_heim.name, self.verein_gast.name, self.datum_zeit)

    def ergebnis(self):
        return '%s:%s' % (self.tore_heim_gesamt, self.tore_gast_gesamt)
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

In deinen urlpatterns auf eine View-Funktion verweisen und die Objekte mit Hilfe der Template-Sprache darstellen:

Code: Alles auswählen

def tabelle(request):
    return render_to_response('tabelle.html', {'vereine':Verein.objects.all()})
Das Model anpassen:

Code: Alles auswählen

class Verein(models.Model):
    name = models.CharField(max_length=100)
    link = models.URLField(verify_exists=True, max_length=200, blank=True)

    class Meta:
        verbose_name_plural = 'Vereine'

    def __unicode__(self):
        return self.name

    @property
    def punkte(self):
        siege = Spiele.objects.filter(sieger=self)
        unentschieden = self.spiele.filter(unentschieden=True)
        return siege*3 + unentschieden
Template:

Code: Alles auswählen

{% for verein in vereine %}
{{ verein.name }} {{ verein.punkte }}
{% endfor %}
Der Code hier passt jetzt nicht direkt auf dein Beispiel, obwohl ich da auch an den Models noch was ändern würde (siehe Beispiel).
cuthbert
User
Beiträge: 5
Registriert: Samstag 11. August 2007, 14:43

Danke schonmal für die Hinweise.

Ok, das mit der View/Template sieht bei mir fast genauso aus (natürlich fehlten die Punkte bisher...).
Aber ich habe noch eine Frage zum Verständnis bzgl. der Model-Änderungen:
Sollte es für die Berechnung der Punkte dann im Spiele-Model die Felder 'sieger' sowie 'unentschieden' geben oder sollte dies auch über Funktionen/Properties geschehen?
Ich habe es mit Properties versucht, aber das scheint nicht zu funktionieren.
Extra Felder für 'sieger' etc. anzulegen fände ich unschön, da die Information darüber ja schon implizit durch das Ergebnis vorliegt.
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

du kannst der Klasse Spiel ja auch wieder ein Property "sieger" hinzufügen:

Code: Alles auswählen

class Spiel(models.Model):
    ...
    @property
    def sieger(self):
        if self.tore_heim > self.tore_gast:
            return self.heim_verein
        elif self.tore_heim == self.tore_gast:
            return None
        else:
           return self.gast_verein
Das funktioniert dann auch problemlos mit meinem Beispiel oben und du kannst dir das "unentschieden" sparen, indem du "sieger" auf None überprüfst.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Einige Logik kann man in den ModelManager packen: http://docs.djangoproject.com/en/dev/to ... /managers/

Ich versuche dort allerdings nur "allgemeine" Sachen unterzubringen, die man an mehrere Stellen gebrauchen kann. Spezielle Dinge kommen dann in den View rein.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
cuthbert
User
Beiträge: 5
Registriert: Samstag 11. August 2007, 14:43

Anscheinend gibt es mit der Property 'sieger' Probleme.
Habe es wie von SchneiderWeisse vorgeschlagen übernommen, dabei erhalten ich dann folgende Fehlermeldung:

Code: Alles auswählen

Caught an exception while rendering: Cannot resolve keyword 'sieger' into field. Choices are: datum_zeit, gespielt, id, schiedsrichter1, schiedsrichter2, spielort, spieltag, tore_gast_gesamt, tore_heim_gesamt, verein_gast, verein_heim
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Ja, da hatte ich wohl einen Denkfehler drin... musst es dann entweder über ModelManager oder manuell machen.
Antworten