user6393083
user6393083

Reputation:

how do you slugify a url?

I'm using slugify, and I have no idea how to make my post title slugified, do I need to make a new column in my post? I've been stuck on this all day long.

Any suggestions ?

Views.py

@app.route('/posts/<title>')
@login_required
def show(title):

    link = db.session.query(Post).filter_by(title = title).one()
    link2 = slugify(link.title)

    return render_template("post.html", post=link2,  pid=id, title=link2)

Models.py

class Post(db.Model):
    __tablename__ = "posts"
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(80))
    body = db.Column(db.Text)




    def __init__(self, title, body):
        self.title = title
        self.body = body

error message

  File "C:\Program Files\Python35-32\lib\site-packages\sqlalchemy\orm\query.py", line 2760, in one
    raise orm_exc.NoResultFound("No row was found for one()")
sqlalchemy.orm.exc.NoResultFound: No row was found for one()

Upvotes: 0

Views: 3725

Answers (2)

Vivek R
Vivek R

Reputation: 676

You take slug instead of title in your view and query database based on slug. While creating post you slugify the title and store it in slug field.

Views.py

@app.route('/posts/<slug>')
@login_required
def show(slug):
    post = db.session.query(Post).filter_by(slug = slug).first()
    if post:
        return render_template("post.html", post=post)

    abort(404)

Note that we are using .first instead of .one here because .first return None if no posts found whereas .one raises an exception which you need to catch and make flow according to it.

If there is no post found then we are returning 404.

Models.py

class Post(db.Model):
    __tablename__ = "posts"
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(80))
    body = db.Column(db.Text)
    slug = db.Column(db.String(80), index=True)

    def __init__(self, title, body):
        self.title = title
        self.body = body
        self.slug = slugify(title)

Upvotes: 2

Kostas Pelelis
Kostas Pelelis

Reputation: 1342

My guess is you are using a title for the posts such as "This is my first blog post" which is great. I am also guessing that you want to use the slug in order to have a more URL friendly permalink for each post. In the previous case the slug would be something like "this-is-my-first-blog-post"

So given a slug, your post would be available at the /posts/{unique-post-slug} route and not /posts/{title}. My suggestion would be to store the slug in the database in order to retrieve the post since reverse slugify isn't so easy.

To sum up your model should be:

class Post(db.Model):
    __tablename__ = "posts"

    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(80))
    body = db.Column(db.Text)
    slug = db.Column(db.Text, index=True)

    def __init__(self, title, body):
        self.title = title
        self.body = body
        self.slug = slugfiy(title)

Notice the index=True option. This is done for faster querying.

And the route that should render your post would be

@app.route('/posts/<slug>')
@login_required
def show(slug):

    post = db.session.query(Post).filter_by(slug=slug).one()

    return render_template("post.html", post=post)

In your post.html file you can use all the post fields (id, title, body, slug) as post.id, post.title, etc

Upvotes: 1

Related Questions