β

用Flask和MongoEngine编写一个轻博客

Zhiwei Li 5002 阅读

http://docs.mongodb.org/ecosystem/tutorial/write-a-tumblelog-application-with-flask-mongoengine/

介绍
本教程描述了 使用流行的Flask框架联合MongoDB数据库建立一个基本的轻博客应用的过程.

轻博客包含两部分
1.一个公开的站点,让人们可以浏览帖子,评论帖子
2.一个管理站点,让你可以增加和修改帖子

本教程假定你已经熟悉Flask 并基本了解MongoDB,并且已经安装了MongoDB. 我们使用MongoEngine作为对象文档映射器(ODM)
这个组件可以满足Flask和MongoDB之间的交互.

安装
用pip和virtualenv来隔离Python环境,安装的python 包跟主系统中的无关.

$ virtualenv myproject
或者
virtualenv -p /usr/bin/python3.3 venv  (--extra-search-dir)
比用 pyvenv3靠谱
source myproject/bin/activate

准备需要的包
Flask是一个微框架,因为它提供非常小的核心功能,高度可扩展.对于 轻博客 项目,本教程包含下面的扩展
WTForms, 提供简单的form处理
Flask-MongoEngine, 提供在MongoEngine, Flask和WTForms之间的集成
Flask-Script 简单使用开发服务器

pip install flask
pip install flask-script
pip install WTForms
pip install mongoengine
pip install flask_mongoengine

开始建立博客
在工程目录下,创建一个 tmubleblog的目录
myproject$ mkdir tumblelog
在该目录下添加 如下文件

__init__.py
from flask import Flask
app = Flask(__name__)
if __name__ == '__main__':
    app.run()

manage.py用来载入额外的Flask-script, 它提供欧冠你一个开发服务器和shell

# Set the path
import os, sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from flask.ext.script import Manager, Server
from tumblelog import app
manager = Manager(app)
# Turn on debugger by default and reloader
manager.add_command("runserver", Server(
    use_debugger = True,
    use_reloader = True,
    host = '0.0.0.0')
)
if __name__ == "__main__":
    manager.run()

在测试服务器里运行这个应用

python manage.py runserver

如果运行正常,你访问 http://localhost:5000 就会看到 404的信息

配置MongoEngine和Flask
安装Flask扩展,增加配置文件.

tumblelog/__init__.py
from flask import Flask
from flask.ext.mongoengine import MongoEngine
app = Flask(__name__)
app.config["MONGODB_SETTINGS"] = {'DB': "my_tumble_log"}
app.config["SECRET_KEY"] = "KeepThisS3cr3t"
db = MongoEngine(app)
if __name__ == '__main__':
    app.run()

定义数据库Schema
用Flask写轻博客的第一步,就是定义 ’Models’(在MongdoDB中叫做 documents)
在这个应用中,你将定义帖子post和评论comments, 所以,每个Post,都包含一个 Comments
编辑 models.py文件

import datetime
from flask import url_for
from tumblelog import db
class Post(db.Document):
    created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
    title = db.StringField(max_length=255, required=True)
    slug = db.StringField(max_length=255, required=True)
    body = db.StringField(required=True)
    comments = db.ListField(db.EmbeddedDocumentField('Comment'))
    def get_absolute_url(self):
        return url_for('post', kwargs={"slug": self.slug})
    def __unicode__(self):
        return self.title
    meta = {
        'allow_inheritance': True,
        'indexes': ['-created_at', 'slug'],
        'ordering': ['-created_at']
    }
class Comment(db.EmbeddedDocument):
    created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
    body = db.StringField(verbose_name="Comment", required=True)
    author = db.StringField(verbose_name="Name", max_length=255, required=True)

MongoEngine的语法是简单 易懂的, 如果你有 Django背景,语法看上去很熟悉.
这个例子为Post定义了索引: 一个是cteated_at 日期,我们的前端页面将按照日期排序
另外一个是单独的帖子slug

用Shell来添加数据
manage.py提供一个shell接口给应用,你可以用它来插入数据到轻博客中.
配置urls和views之前,你可以用这个接口来同你的轻博客 交互.
启动shell

python manage.py shell

用下面的操作,建立第1个帖子

>>> from tumblelog.models import *
>>> post = Post(
... title="Hello World!",
... slug="hello-world",
... body="Welcome to my new shiny Tumble log powered by MongoDB, MongoEngine, and Flask"
... )
>>> post.save()

添加一些评论

>>> post.comments
[]
>>> comment = Comment(
... author="Joe Bloggs",
... body="Great post! I'm looking forward to reading your blog!"
... )
>>> post.comments.append(comment)
>>> post.save()

最后,可以查看这个帖子

>>> post = Post.objects.get()
>>> post
>>> post.comments
[]

添加视图(Views)
使用Flask基于类的视图系统,允许你为轻博客产生List和Details视图
添加views.py,并建立一个post的蓝图(blueprint)

from flask import Blueprint, request, redirect, render_template, url_for
from flask.views import MethodView
from tumblelog.models import Post, Comment
posts = Blueprint('posts', __name__, template_folder='templates')
class ListView(MethodView):
    def get(self):
        posts = Post.objects.all()
        return render_template('posts/list.html', posts=posts)
class DetailView(MethodView):
    def get(self, slug):
        post = Post.objects.get_or_404(slug=slug)
        return render_template('posts/detail.html', post=post)
# Register the urls
posts.add_url_rule('/', view_func=ListView.as_view('list'))
posts.add_url_rule('//', view_func=DetailView.as_view('detail'))

现在到应用的init.py里注册蓝图
通过在一个方法里注册蓝图,可避免循环依赖.

def register_blueprints(app):
    # Prevents circular imports
    from tumblelog.views import posts
    app.register_blueprint(posts)
register_blueprints(app)

添加模板
在tumblelog目录下,添加templates目录和templates/posts目录,用来存储temblelog的模板

mkdir -p templates/posts

建立一个基本的模板,其他所有模板都将从这个模板里继承. templates/base.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>My Tumblelog</title>
    <link href="http://twitter.github.com/bootstrap/1.4.0/bootstrap.css" rel="stylesheet">
    <style>.content {padding-top: 80px;}</style>
  </head>
  <body>
    {%- block topbar -%}
    <div class="topbar">
      <div class="fill">
        <div class="container">
          <h2>
              <a href="http://zhiwei.li/" class="brand">My Tumblelog</a> <small>Starring Flask, MongoDB and MongoEngine</small>
          </h2>
        </div>
      </div>
    </div>
    {%- endblock -%}
    <div class="container">
      <div class="content">
        {% block page_header %}{% endblock %}
        {% block content %}{% endblock %}
      </div>
    </div>
    {% block js_footer %}{% endblock %}
  </body>
</html>

为博客建立一个landing 页面,它将列出所有的帖子.
templates/posts/list.html

{% extends "base.html" %}
{% block content %}
    {% for post in posts %}
      <h2><a href="{{ url_for('posts.detail', slug=post.slug) }}">{{ post.title }}</a></h2>
      <p>{{ post.body|truncate(100) }}</p>
      <p>
        {{ post.created_at.strftime('%H:%M %Y-%m-%d') }} |
        {% with total=post.comments|length %}
            {{ total }} comment {%- if total > 1 %}s{%- endif -%}
        {% endwith %}
      </p>
    {% endfor %}
{% endblock %}

最后 添加templates/posts/detail.html模板,用来显示单独的帖子

-------

代码写到这里,你运行 python manage.py runserver 就可以看到你的轻博客了.

给博客添加评论
接下来,你将给读者添加在帖子后面留下评论的功能.用WTForms就可以创建表单,它会更新处理表单数据的视图,也会更新包含在表单里的模板

在视图里处理评论
更新和重构views.py,以便它能处理表单.增加import语句和DetailView类

from flask.ext.mongoengine.wtf import model_form
...
class DetailView(MethodView):
    form = model_form(Comment, exclude=['created_at'])
    def get_context(self, slug):
        post = Post.objects.get_or_404(slug=slug)
        form = self.form(request.form)
        context = {
            "post": post,
            "form": form
        }
        return context
    def get(self, slug):
        context = self.get_context(slug)
        return render_template('posts/detail.html', **context)
    def post(self, slug):
        context = self.get_context(slug)
        form = context.get('form')
        if form.validate():
            comment = Comment()
            form.populate_obj(comment)
            post = context.get('post')
            post.comments.append(comment)
            post.save()
            return redirect(url_for('posts.detail', slug=slug))
        return render_template('posts/detail.html', **context)

注意:DetailView扩展自默认的Flask MothodView.

增加站点管理界面
当然,你可以总是使用shell来发布帖子.下面我们介绍如果给轻博客添加管理界面.
你将增加认证和另外的视图.本教程只集中于 添加和编辑帖子. ”删除”

作者:Zhiwei Li
又一个WordPress站点
原文地址:用Flask和MongoEngine编写一个轻博客, 感谢原作者分享。

发表评论