2009-09-29 15 views
7

Ich arbeite gerade an einem Spielzeugprojekt in Django.Django slugified urls - wie mit Kollisionen umzugehen?

Ein Teil meiner App ermöglicht Benutzern, Bewertungen zu verlassen. Ich würde gerne den Titel der Rezension nehmen und ihn verschicken, um eine URL zu erstellen.

Also, wenn ein Benutzer eine Rezension namens "Das beste Ding überhaupt!" Schreibt, wäre die URL etwa so: www.example.com/reviews/the-best-thing-ever.

Das ist alles gut und gut, aber was ist der beste Weg, Fall zu behandeln, wo zwei Benutzer den gleichen Titel wählen? Ich möchte nicht, dass der Titel erforderlich ist, um einzigartig zu sein.

Ich habe über das Hinzufügen der Review-ID in der URL irgendwo nachgedacht, aber ich möchte diese zusätzlichen Informationen für alle URLs vermeiden, die nicht kollidieren.

Irgendwelche Ideen?

Antwort

6

Eine Sache, die ich an den einzigartigen Slug-Feldern/Methoden nie gemocht habe, ist, dass wenn du viele Zusammenstöße für einen einzelnen Titel hast, du mehrere Abfragen ausführst, um einen verfügbaren Slug zu finden. Ich weiß, dass du erwähnt hast, dass du die ID nicht für nicht-zusammenstoßende Nacktschnecken zeigen willst, aber was die Leistung angeht, denke ich, dass es der bessere Weg ist. Um die URL ein wenig netter zu machen, bevorzuge ich es auch, die ID vor der Slug einzubetten, so dass eine URL die Form von www.example.com/reviews/1-the-best-thing-ever hat.

+0

Dies ist die Lösung hinzufügen Ich habe darüber nachgedacht, obwohl Slug sich in diesem Fall als sinnlose Augenweide erweist. Es ist schnell und befreit dich von diesem Problem vollständig. In einer "echten" App würde ich wahrscheinlich diesen Weg nehmen, aber ich bin immer noch daran interessiert, wie man damit umgehen und trotzdem nicht kollidierende URLs völlig frei von irgendwelchen IDs machen kann. –

+1

Ich sollte auch beachten, dass dies der gleiche Ansatz zu sein scheint, den SO verwendet, wenn Sie auf die URL-Leiste blicken :) –

+0

Nun, es sieht so aus, als wäre ich in guter Gesellschaft. Was die Beseitigung aller IDs betrifft, sind die beiden anderen Antworten definitiv der richtige Weg. Als ich anfing, Dinge zu verprügeln, benutzte ich eine einzigartige Slug-Methode, die ich irgendwo gefunden habe (sie ist fast identisch mit der, die Zalew gepostet hat). – Adam

2
from django.template.defaultfilters import slugify 

def slugify_unique(value, model, slugfield="slug"): 
     suffix = 0 
     potential = base = slugify(value) 
     while True: 
      if suffix: 
       potential = "-".join([base, str(suffix)]) 
      if not model.objects.filter(**{slugfield: potential}).count(): 
       return potential 
      suffix += 1  
""" 
above function is not my code, but i don't remember exactly where it comes from 
you can find many snippets with such solutions searching for 'unique slug' and so 
""" 


class ReviewForm(forms.ModelForm): 

    def save(self, user, commit=True):  
     self.instance.slug = slugify_unique(self.cleaned_data['title'], self.Meta.model)      
     review = super(ReviewForm, self).save(commit) 
     review.save() 
     return review 

    class Meta: 
     model = Review 

natürlich ändern Sie die entsprechenden Namen und Formulardefinition, aber Sie bekommen die Idee :)

6

ich so etwas wie AutoSlugField empfehlen würde. Es verfügt über einige Optionen für die Konfiguration der Eindeutigkeit (unique und unique_with) und bietet den zusätzlichen Vorteil, dass Sie auf der Grundlage eines anderen Felds in Ihrem Modell automatisch Slugs generieren können, wenn Sie dies wünschen.

0

würde ich (bei der Validierung Form) nur überprüfen, um zu sehen, ob die Schnecke verwendet wird, und dann etwas, um es, entweder eine Zahl „my-cool-idea_2“ oder die tatsächliche ID