前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python flask web 博客实例 博客模块 2

python flask web 博客实例 博客模块 2

作者头像
用户5760343
发布2019-07-05 11:10:21
4500
发布2019-07-05 11:10:21
举报
文章被收录于专栏:sktjsktj

1  app/models.py from markdown import markdown import bleach class Post(db.Model): tablename = 'posts' id = db.Column(db.Integer, primary_key=True) body = db.Column(db.Text) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) author_id = db.Column(db.Integer, db.ForeignKey('users.id')) @staticmethod def on_changed_body(target, value, oldvalue, initiator): allowed_tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code','em', 'i', 'li', 'ol', 'pre','strong', 'ul','h1', 'h2', 'h3', 'p'] target.body_html = bleach.linkify(bleach.clean(markdown(value,output_format='html'),tags=allowed_tags, strip=True)) db.event.listen(Post.body, 'set', Post.on_changed_body) class User(UserMixin, db.Model): # ... posts = db.relationship('Post', backref='author', lazy='dynamic') @staticmethod def generate_fake(count=100): from sqlalchemy.exc import IntegrityError from random import seed import forgery_py

代码语言:javascript
复制
    seed()
    for i in range(count):
        u = User(email=forgery_py.internet.email_address(),
                 username=forgery_py.internet.user_name(True),
                 password=forgery_py.lorem_ipsum.word(),
                 confirmed=True,
                 name=forgery_py.name.full_name(),
                 location=forgery_py.address.city(),
                 about_me=forgery_py.lorem_ipsum.sentence(),
                 member_since=forgery_py.date.date(True))
        db.session.add(u)
        try:
            db.session.commit()
        except IntegrityError:
            db.session.rollback()

class Post(db.Model): @staticmethod def generate_fake(count=100): from random import seed, randint import forgery_py

代码语言:javascript
复制
    seed()
    user_count = User.query.count()
    for i in range(count):
        u = User.query.offset(randint(0, user_count - 1)).first()
        p = Post(body=forgery_py.lorem_ipsum.sentences(randint(1, 5)),
                 timestamp=forgery_py.date.date(True),
                 author=u)
        db.session.add(p)
        db.session.commit()

2 app/main/forms.py from flask.ext.pagedown.fields import PageDownField class PostForm(Form): body = PageDownField(("What's on your mind?", validators=[Required()]) submit = SubmitField('Submit')

3 app/main/views.py @main.route('/', methods=['GET', 'POST']) def index(): form = PostForm() if current_user.can(Permission.WRITE_ARTICLES) and form.validate_on_submit(): post = Post(body=form.body.data, author=current_user._get_current_object()) db.session.add(post) return redirect(url_for('.index')) # ... page = request.args.get('page', 1, type=int) pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'],error_out=False) posts = pagination.items return render_template('index.html', form=form, posts=posts,pagination=pagination) @main.route('/user/<username>') def user(username): user = User.query.filter_by(username=username).first() if user is None: abort(404) posts = user.posts.order_by(Post.timestamp.desc()).all() return render_template('user.html', user=user, posts=posts) @main.route('/post/<int:id>') def post(id): post = Post.query.get_or_404(id) return render_template('post.html', posts=[post]) @main.route('/edit/<int:id>', methods=['GET', 'POST']) @login_required def edit(id): post = Post.query.get_or_404(id) if current_user != post.author and not current_user.can(Permission.ADMINISTER): abort(403) form = PostForm() if form.validate_on_submit(): post.body = form.body.data db.session.add(post) flash('The post has been updated.') return redirect(url_for('.post', id=post.id)) form.body.data = post.body return render_template('edit_post.html', form=form)

4  app/templates/index.html {% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% import "_macros.html" as macros %} ... <div> {% if current_user.can(Permission.WRITE_ARTICLES) %} {{ wtf.quick_form(form) }} {% endif %} </div> <ul class="posts"> {% for post in posts %} <li class="post"> <div class="profile-thumbnail"> <a href="{{ url_for('.user', username=post.author.username) }}"> <img class="img-rounded profile-thumbnail" src="{{ post.author.gravatar(size=40) }}"> </a> </div> <div class="post-date">{{ moment(post.timestamp).fromNow() }}</div> <div class="post-author"> <a href="{{ url_for('.user', username=post.author.username) }}"> {{ post.author.username }} </a> </div> <div class="post-body">{{ post.body }}</div> </li> {% endfor %} </ul> {% include '_posts.html' %} <div class="pagination"> {{ macros.pagination_widget(pagination, '.index') }} </div> {% endif %}

5  app/templates/user.html <h3>Posts by {{ user.username }}</h3> {% include '_posts.html' %}

6 生成虚拟数据:pip install forgerypy $ python manage.py shell

User.generate_fake(100) Post.generate_fake(100)

7 app/templates/_macros.html {% macro pagination_widget(pagination, endpoint, fragment='') %} <ul class="pagination"> <li{% if not pagination.has_prev %} class="disabled"{% endif %}> <a href="{% if pagination.has_prev %}{{ url_for(endpoint, page=pagination.prev_num, **kwargs) }}{{ fragment }}{% else %}#{% endif %}"> « </a> </li> {% for p in pagination.iter_pages() %} {% if p %} {% if p == pagination.page %} <li class="active"> <a href="{{ url_for(endpoint, page = p, **kwargs) }}{{ fragment }}">{{ p }}</a> </li> {% else %} <li> <a href="{{ url_for(endpoint, page = p, **kwargs) }}{{ fragment }}">{{ p }}</a> </li> {% endif %} {% else %} <li class="disabled"><a href="#">…</a></li> {% endif %} {% endfor %} <li{% if not pagination.has_next %} class="disabled"{% endif %}> <a href="{% if pagination.has_next %}{{ url_for(endpoint, page=pagination.next_num, **kwargs) }}{{ fragment }}{% else %}#{% endif %}"> » </a> </li> </ul> {% endmacro %}

8 pip install flask-pagedown markdown bleach #添加富文本编辑器 9 app/init.py from flask.ext.pagedown import PageDown

...

pagedown = PageDown()

...

def create_app(config_name): # ... pagedown.init_app(app) # ...

10 app/index.html {% block scripts %} {{ super() }} {{ pagedown.include_pagedown() }} {% endblock %}

paginate对象方法

image.png

image.png

11 app/templates/_posts.html <ul class="posts"> {% for post in posts %} <li class="post"> <div class="post-thumbnail"> <a href="{{ url_for('.user', username=post.author.username) }}"> <img class="img-rounded profile-thumbnail" src="{{ post.author.gravatar(size=40) }}"> </a> </div> <div class="post-content"> <div class="post-date">{{ moment(post.timestamp).fromNow() }}</div> <div class="post-author"><a href="{{ url_for('.user', username=post.author.username) }}">{{ post.author.username }}</a></div> <div class="post-body"> {% if post.body_html %} {{ post.body_html | safe }} {% else %} {{ post.body }} {% endif %} </div> <div class="post-footer"> {% if current_user == post.author %} <a href="{{ url_for('.edit', id=post.id) }}"> <span class="label label-primary">Edit</span> </a> {% elif current_user.is_administrator() %} <a href="{{ url_for('.edit', id=post.id) }}"> <span class="label label-danger">Edit [Admin]</span> </a> {% endif %} <a href="{{ url_for('.post', id=post.id) }}"> <span class="label label-default">Permalink</span> </a> <a href="{{ url_for('.post', id=post.id) }}#comments"> <span class="label label-primary">{{ post.comments.count() }} Comments</span> </a> </div> </div> </li> {% endfor %} </ul>

12 app/templates/post.html {% extends "base.html" %} {% block title %}Flasky - Post{% endblock %} {% block page_content %} {% include '_posts.html' %} {% endblock %}

13 app/templates/edit_post.html {% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% block title %}Flasky - Edit Post{% endblock %} {% block page_content %} <div class="page-header"> <h1>Edit Post</h1> </div> <div> {{ wtf.quick_form(form) }} </div> {% endblock %} {% block scripts %} {{ super() }} {{ pagedown.include_pagedown() }} {% endblock %}

db.event.listen(Post.body, 'set', Post.on_changed_body) 的作用

image.png

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.05.27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ...
  • ...
  • paginate对象方法
  • db.event.listen(Post.body, 'set', Post.on_changed_body) 的作用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档