in Flask, PYTHON, Web Development

Change of plans…sort of…kind of…

I am currently reconsidering my options as far as the database for FlaskCasts. As a newbie to Flask and Python, I am starting to see that MongoDB may be more challenging to use than I had initially thought. However, I’m not one to give up so soon. A couple of things I am confused about stand out:

  1. Implementing Pagination for the list of videos on the front page.
  2. Sorting those in descending order.

Coming from an SQL background this isn’t so complicated and in fact a lot of the SQLAlchemy based libraries have a pagination method built in.

Right now I am looking at the Flask-PyMongo extension to see if this will make things any easier. So far I have used plain PyMongo (on my blog attempt I mentioned earlier) and wrote a lot of the DB methods myself. I’ve already came across YouTube videos showing how to sort with this library so I think I may be able to use this and roll my own pagination.

After a little more research, I found Flask-MongoEngine. With just a little tinkering I was able to implement a very basic pagination. So I am pretty happy with that. This library seems to be well supported so I may just stick with this.

from flask import Flask, request, Blueprint, render_template
from flask_mongoengine import *
from .models import Post

app = Flask(__name__)
app.config.from_object('config')
db = MongoEngine(app)

@app.route('/')
def hello_world():
    page = int(request.args.get('page') or 1)
    posts = Post.objects.order_by('-created')
    paginated_posts = Pagination(posts, page=page, per_page=2)
    return render_template('index.html', paginated_posts=paginated_posts)

This is my view. Basically it checks to see if a page variable is being passed through. Gets the posts in descending order. Passes the posts to the Pagination class that is built in with the current page and showing only 2 entries per page. Then it renders the template with the paginated_posts.

{% for post in paginated_posts.items %}
    <h2>{{ post.title }}</h2>
    <p>{{ post.content }}</p>
    <p>Posted by: {{ post.author.fullname }}</p>
{% endfor %}

{# Macro for creating navigation links #}
{% macro render_navigation(pagination, endpoint) %}
  <div class=pagination>
  {% for page in pagination.iter_pages() %}
    {% if page %}
      {% if page != pagination.page %}
        <a href="{{ url_for(endpoint, page=page) }}">{{ page }}</a>
      {% else %}
        <strong>{{ page }}</strong>
      {% endif %}
    {% else %}
      <span class=ellipsis>…</span>
    {% endif %}
  {% endfor %}
  </div>
{% endmacro %}

{{ render_navigation(paginated_posts, 'hello_world') }}

I’d never really messed wtih a Macro in Jinja before this so I need to do a little more studying to get a grasp on what is happening here.  But…it works, and is much easier to roll out than anything else I think I could have done.

The models are a bit confusing as these classes inherit from the Document class…and I have not yet worked with anything like this, I’ve written my own classes. I am going to play around with the concepts a little more to get confortable. Here is what they look like right now:

import datetime
from mongoengine import *


class User(Document):
    email = EmailField()
    password = StringField()
    fullname = StringField()


class Post(Document):
    title = StringField()
    content = StringField()
    author = ReferenceField(User)
    created = DateTimeField(datetime.datetime.now)

Going to work on this some more tomorrow. Very happy to have solved this pagination issue however.

 

Write a Comment

Comment