用flask編寫本身的博客(1)

照着視頻寫代碼!由於底子緣由,進度太慢,對其中的部分代碼和知識點進行記錄html

1、設計models:

​ 本着簡單的原則設計,只包函user、post、comments 三個表格,user爲用戶信息,post爲文章列表,comments爲評論列表,代碼以下:python

from . import db, login_manager
from flask_login import UserMixin
# import datetime
from datetime import datetime
from markdown import markdown
from werkzeug.security import generate_password_hash, check_password_hash
import bleach

class Role(db.Model):
    __tablename__ = "roles"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=True)
    users = db.relationship("User", backref='roles')

    @staticmethod
    def seed():
        db.session.add_all(map(lambda r: Role(name=r), ["Guest", "Administrator"]))
        db.session.commit()

class User(db.Model, UserMixin):
    __tablename__ = "users"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=True)
    nickname = db.Column(db.String(64), nullable=True)
    email = db.Column(db.String(255))
    password_hash = db.Column(db.String(255), nullable=True)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    posts = db.relationship("Post", backref='author')
    commnets = db.relationship("Comment", backref='comment')

    @staticmethod
    def on_created(target, value, oldvalue, initiator):
        target.role = Role.query.filter_by(name="Guest").first()
    #設置禁止讀取password
    @property
    def password(self):
        raise AttributeError('Password is not a readable attribute')
    #hash密碼
    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)
    #檢查密碼是否匹配,返回bool值
    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

#監聽建立用戶事件
db.event.listen(User.name, "set", User.on_created)

class Post(db.Model):
    __tablename__ = "posts"
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64), nullable=True)#MySQL須要字符串長度,sqlite能夠不設
    body = db.Column(db.String(5000), nullable=True)
    body_html = db.Column(db.String(5000), nullable=True)
    created = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    comments = db.relationship("Comment", backref="posts")
    author_id = db.Column(db.Integer, db.ForeignKey("users.id"))

    @staticmethod
    def on_body_changed(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_body_changed)

class Comment(db.Model):
    __tablename__ = "comments"
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(200), nullable=True)
    created = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    post_id = db.Column(db.Integer, db.ForeignKey("posts.id"))
    author_id = db.Column(db.Integer, db.ForeignKey("users.id"))

2、建立wtf表單:登錄、註冊、修改密碼、新增(修改)、評論

from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField
from wtforms.validators import DataRequired
from flask_pagedown.fields import PageDownField
#新增(修改)表單
class PostForm(FlaskForm):
    title = StringField('標題',validators=[DataRequired()])
    body=PageDownField("正文",validators=[DataRequired()])
    submit=SubmitField("發佈")
#評論表單
class CommentForm(FlaskForm):
    body=PageDownField("評論",validators=[DataRequired()])
    submit=SubmitField("發表")
from flask_wtf import FlaskForm as Form
from wtforms import StringField, PasswordField, SubmitField, SelectField
from wtforms.validators import DataRequired, EqualTo, Email, Regexp, Length
from app.models import Role

class LoginForm(Form):
    username = StringField(validators=[DataRequired()], label="用戶名")
    password = PasswordField(validators=[DataRequired()], label="密 碼")
    submit = SubmitField(label="提交")

class RegistrationFrom(Form):
    email = StringField(u"郵箱地址", validators=[DataRequired(), Length(1, 64), Email()])
    nickname = StringField("暱稱", validators=[DataRequired()])
    username = StringField(u"用戶名", validators=[DataRequired(), Length(1, 64), Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0,
                                                                                     u"用戶名必須由字母開頭,字母、數字、下劃線或 . 組成")])
    password = PasswordField(u"密碼", validators=[DataRequired(), EqualTo('password2', message=u'兩次密碼不一致')])
    password2 = PasswordField(u"確認密碼", validators=[DataRequired()])
    authed = SelectField(u'權限', coerce=int)
    submit = SubmitField(u"當即註冊")

    # SelectFrom Data 數據須要注意,多個列表直接在init裏面添加
    def __init__(self, *args, **kwargs):
        super(RegistrationFrom, self).__init__(*args, **kwargs)
        self.authed.choices = [(role.id, role.name) for role in Role.query.order_by(Role.id).all()]

class PasswdChangeFrom(Form):
    user = StringField(u"用戶名", validators=None)
    nickname = StringField("暱稱")
    # old_password = HiddenField(validators=[DataRequired()])
    password = PasswordField(u'新密碼', validators=[DataRequired(), Length(6, 16, message="密碼長度不合適,請輸入6-16位密碼"),
                                                 EqualTo("password2", message=u"兩次密碼不一致")])
    password2 = PasswordField(u"重複密碼", validators=[DataRequired()])
    submit = SubmitField(u"提交")

註冊和修改密碼對安全性要求較高,作了一些限制:郵箱有效性、用戶名規則、用戶名是否存在、密碼長度等git

第二彈:對項目的結構進行分析!使用blueprint進行分組,減小單個文件的大小傳送門github

第三彈:對jinja2 網頁模板進行分析,使用bootstrap+wtf快速佈局(待續)sql

第四彈,整個項目的總結以及擴展,qrcode等一些小工具的介紹(...)flask

項目源碼地址:github
教學視頻地址:Flask入門bootstrap

相關文章
相關標籤/搜索