Django: Instanz auf Existenz überprüfen

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

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
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Du kannst IMHO besser ein slugfield nutzten, das ist genau dafür da: http://www.djangoproject.com/documentat ... #slugfield

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

@Hmpf, würde aber die URL gern im tinyurl-Style machen, aber trotzdem danke

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