Seite 1 von 1

[Django] choice daten anders festhalten als in einem Tuple..

Verfasst: Donnerstag 19. Februar 2009, 09:36
von jens
Es lohnt sich ja nicht immer für ein kleine Auswahl (für ein choice Feld) eine eigene Modell-Klasse zu machen. Erst recht dann nicht, wenn es sich quasi um Konstanten handelt.

Man kann choices ja in einem Tuple stopfen und in forms oder models nutzten, beispiele findet man hier: http://docs.djangoproject.com/en/dev/re ... s/#choices

Was ich meine ist sowas:

Code: Alles auswählen

TYPE_CHOICES = (
  (0, "wiki page"),
  (1, "cms page"),
  (2, "blog entry"),
  (3, "static file"),
)
Aber irgendwie ist das dumm. Früher oder später wird man im Code eine Verknüpfung der ID mit dem Text haben wollen. Also muß man garantieren, das die ID überall das selbe meint. Nun könnte man das machen:

Code: Alles auswählen

TYPE_WIKI = 0
TYPE_CMS = 1
TYPE_BLOG = 2
TYPE_FILE = 3

TYPE_CHOICES = (
  (TYPE_WIKI, "wiki page"),
  (TYPE_CMS, "cms page"),
  (TYPE_BLOG, "blog entry"),
  (TYPE_FILE, "static file"),
)
Nun kann man die "Konstanten" in andere Module importieren und damit arbeiten. Ist aber alles ein wenig viel Tipparbeit... Aber, wenn eine ID ändert, dann muß man keine anderen Code Teile ändern. Außerdem sieht man überall im Code, das hinter eine ID steckt, weil man ja nicht die Zahl nimmt, sondern die Variable...

Eine andere Variante wäre das:

Code: Alles auswählen

TYPE_CHOICES = (
  ("wiki", "wiki page"),
  ("cms", "cms page"),
  ("blog", "blog entry"),
  ("file", "static file"),
)
Ist aber auch nicht so richtig schön, weil man nun z.B. in einem Modell nicht mehr ein einfaches Integer Feld nehmen kann... Auf der anderen Seite kann man sogar direkt in der Datenbank sehen um was für ein Typ es sich handelt.
OK, man könnte auch nur immer ein oder zwei Buchstaben nehmen, statt dem ganzen Wort, aber dann ist das auch nicht mehr ganz so eindeutig...

Es gibt auch situationen wo hinter diesem Typ auch z.B. verschiedene methoden einer klasse oder Funktionen stehen. Dann wäre es nett, wenn man sowas einfacher machen könnte:

Code: Alles auswählen

if item == 0:
    call_wiki(foo, bar)
elif item == 1:
    call_cms(foo, bar)
...
else:
    raise Error...
Ich überlege ob es nicht Sinn macht, irgendein Objekt sich zu bauen, was die Verwaltung einfacher machen könnte... Hat jemand sowas schon gemacht? Oder wie macht ihr das???

Verfasst: Donnerstag 19. Februar 2009, 10:15
von apollo13
Google hilft, james bennet hat auch schon darüber geschrieben, in den Kommentaren steht dann einiges über eigene Objects...

Verfasst: Donnerstag 19. Februar 2009, 13:43
von jens
Du meinst wohl das hier: http://www.b-list.org/weblog/2007/nov/0 ... right-way/

Es gibt noch ein paar Ansätze hier: http://www.djangosnippets.org/tags/choices/ (da sind allerdings viele nicht sehr überzeugend)

Das mit den Konstanten scheint mir noch der beste Weg zu sein, hat Bennett ja auch im Programm:

Code: Alles auswählen

class Entry(models.Model):
    LIVE_STATUS = 1
    DRAFT_STATUS = 2
    HIDDEN_STATUS = 3
    STATUS_CHOICES = (
        (LIVE_STATUS, 'Live'),
        (DRAFT_STATUS, 'Draft'),
        (HIDDEN_STATUS, 'Hidden'),
    )
    # ...some other fields here...
    status = models.IntegerField(choices=STATUS_CHOICES, default=LIVE_STATUS)

Verfasst: Donnerstag 19. Februar 2009, 18:35
von Dauerbaustelle
Jagut, man könnte das auch als Klasse machen. Und dann eben einen List-"Parser" einbauen, für Django.

Verfasst: Freitag 20. Februar 2009, 09:18
von jens
Ach, früher oder später wir man bestimmt mal im view die Bezeichnung anhand der ID haben wollen... Für den Fall kann man auch gleich noch ein dict mit den Daten ablegen, z.B.:

Code: Alles auswählen

class Entry(models.Model):
    LIVE_STATUS = 1
    DRAFT_STATUS = 2
    HIDDEN_STATUS = 3

    STATUS_CHOICES = (
        (LIVE_STATUS, 'Live'),
        (DRAFT_STATUS, 'Draft'),
        (HIDDEN_STATUS, 'Hidden'),
    )
    STATUS_DICT = dict(STATUS_CHOICES)

    # ...some other fields here...
    status = models.IntegerField(choices=STATUS_CHOICES, default=LIVE_STATUS
Dann kann man mit Entry.STATUS_DICT[current_status] an den Namen kommen...