Seite 1 von 1

Django: Instanz auf Existenz überprüfen

Verfasst: Mittwoch 6. August 2008, 22:56
von Dauerbaustelle
Hallo,
experimentiere grade ein wenig mit django und steh vor nem Problem. Ich möchte eine Art Shortlink-Application erstellen. Dazu muss ich überprüfen, ob in der Datenbank ein Eintrag mit der gleichen Shortlink-ID (Aus Ziffern, Klein- und Großbuchstaben, 4 Zeichen lang) exisitert und dann ggf einen neuen generieren.

Nur tut das alles nicht so wie ich will :D

Code: Alles auswählen

from django.db import models
from django.contrib import admin
import random

TYPES = [map(chr, range(97, 123)), map(chr, range(65, 91)), map(int, range(0, 10))]
# Klein- und Grossbuchstaben sowie Ziffern mappen

class ShortLink():
    link = ""
    while True:
        for i in range(4):
            type = random.randint(0, 2)
            n = random.randint(0, len(TYPES[type])-1)
            link += str(TYPES[type][n])
            # Pruefsumme erzeugen
        try:
            self.get(link=link)
            # gibts ihn schon?
        except:
            break
            # wenn nein, brich ab

    def __str__(self):
        return "<ShortLink %s" % self.link


class Link(models.Model):
    url = models.URLField('Adresse')
    date = models.DateTimeField(auto_now=True)
    link = ShortLink()

    def __str__(self):
        return "Link nach %s (%s)" % (self.url, self.link)

    class Meta:
        ordering = ['-date']
        verbose_name = "Link"
        verbose_name_plural = "Links"

admin.site.register(Link)
Ich bin jetzt mal zwei Wochen nicht online, dürft aber trotzdem über meine Art des Codings schimpfen :P

Gruß & Danke

Verfasst: Donnerstag 7. August 2008, 07:36
von jens
Du kannst IMHO besser ein slugfield nutzten, das ist genau dafür da: http://www.djangoproject.com/documentat ... #slugfield

Verfasst: Sonntag 10. August 2008, 09:08
von sma
Was du da machst, ist nicht für den Mehrbenutzerbetrieb geeignet. Nachdem du geprüft hast, dass ein Datensatz nicht existiert aber bevor du reagierst, kann ein anderer Prozess zu der selben Erkenntnis kommen. Theoretisch sollte ein `get_or_create` das machen, was du willst: Nämlich atomar prüfen, ob ein Datensatz existiert oder ihn ggf. anlegen. Leider ist dessen Implementierung abhängig davon, wie Transaktionen in der benutzten Datenbank funktionieren, sodass auch das nicht immer funktioniert.

In keinem Fall würde ich übrigens einfach so alle Exceptions abfangen. Wenn dein `self.get()` auch nur einen NameError, AttributeError oder sonst was wirft, glaubst du, es gibt diesen Namen aber eigentlich hast du einen Fehler im Programm.

Ein verlässlicher, datenbank-übergreifend funktionierender Weg wäre IMHO der über einen speziellen, nur einmal laufenden Server, der auf Anfrage neue IDs liefert - jetzt mit dem Nachteil, dass er ein Single-Point-of-Failure ist. Ein besserer Weg würde mich ebenfalls interessieren.

Stefan

Verfasst: Sonntag 24. August 2008, 23:33
von Dauerbaustelle
@Hmpf, würde aber die URL gern im tinyurl-Style machen, aber trotzdem danke

@sma: get_or_create sehe ich mir mal an. Danke!