How can I hide an id sequence and provide a "friendly" url using pyramid?
<p>I have a list of things in a database and would like to hide the sequence of the primary key from being shown in the url when being accessed. So I would like to turn something like this:</p>

<pre><code>example.com/post/9854
</code></pre>

<p>into this:</p>

<pre><code>example.com/post/one-two-three-four
</code></pre>

<p>While obviously still using the primary key in the query. What is the pyramid way of accomplishing this? </p>

<p>This "user friendly URL fragment" is usually called a "slug", which I think comes from the times when newspapers were typeset in lead.</p>

<p>What you usually do is have an additional field in your model which stores the slug. The field should be unique and indexed (you may even consider having it as your model's primary key depending on where you stand in the great "natural vs surrogate primary keys" debate :) )</p>

<pre><code>class SurrogatePost(Base):
    id = sa.Integer(primary_key=True)
    slug = sa.String(unique=True)
    title = sa.String()

class NaturalPost(Base)
    id = sa.String(primary_key=True)
    title = sa.String()
</code></pre>

<p>You generate the slug from the post's title ONCE when your post is first saved and never change it again, even if the title changes - this is important for SEO and linking.</p>

<pre><code>class Post(Base)
    ...
    def __init__(self, title, body):
        self.slug = generate_slug(title)
        self.title = title
        self.body = body
</code></pre>

<p>Then, in your views code, you use the slug to look up the post in the database, just like you would use your primary key.</p>

<pre><code>   def my_view(request):
       slug = request.matchdict['slug']
       post = DBSession.query(Post).filter(Post.slug==slug).one()
       ...
</code></pre>

<p>The URL schema you're thinking about has a requirement that all slugs of all your posts have to be unique, which may be annoying. If you look at many news websites, you'll notice that they use a "combined" URL scheme, where both primary key and the slug are present in the URL:</p>

<pre><code>/posts/123/one-two-three-four
/posts/123-one-two-three-four
etc.
</code></pre>

<p>The primary key is used to look up the data in the database and the slug part is purely for SEO and readability. </p>

python url url-rewriting url-routing pyramid