照着视频写代码!由于底子缘由,进度太慢,对其中的部分代码和知识点进行记录html
本着简单的原则设计,只包函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"))
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