# -*- coding: utf-8 -*-
import re
import json
import hashlib
from datetime import datetime
from werkzeug import cached_property
from werkzeug.security import generate_password_hash, check_password_hash
from itsdangerous import URLSafeTimedSerializer as Serializer
from jinja2.filters import do_striptags, do_truncate
from flask.ext.sqlalchemy import BaseQuery
from flask import current_app, request, url_for
from flask.ext.login import UserMixin, AnonymousUserMixin
from .ext import db, keywords_split, to_bytes
from .utils.filters import markdown_filter
from config import Config
BODY_FORMAT = Config.BODY_FORMAT
pattern_hasmore = re.compile(r'<!--more-->', re.I)
def markitup(text):
"""
把Markdown转换为HTML
默认不生成高亮代码。
若需要生成高亮代码,需在Setting增加codehilite设置值,类型为int,
值大于0. 另外需要安装Pygments。
"""
try:
_flag = Setting.get('codehilite', False) and True
except:
_flag = False
return markdown_filter(text, codehilite=_flag)
class Permission:
'''定义角色拥有的权限'''
#: 写的文章是草稿,不公开
WRITE_ARTICLES = 0x04
#: 可以公开文章
PUBLISH_ARTICLES = 0x08
#: 上传文件
UPLOAD_FILES = 0x10
#: 管理后台的权限
ADMINISTER = 0x80
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
default = db.Column(db.Boolean, default=False, index=True)
permissions = db.Column(db.Integer)
users = db.relationship('User', backref='role', lazy='dynamic')
__mapper_args__ = {'order_by': [id.desc()]}
@staticmethod
def insert_roles():
roles = {
'User': (Permission.WRITE_ARTICLES, True),
'Moderator': (Permission.WRITE_ARTICLES |
Permission.PUBLISH_ARTICLES, False),
'Administrator': (0xff, False)
}
for r in roles:
role = Role.query.filter_by(name=r).first()
if role is None:
role = Role(name=r)
role.permissions = roles[r][0]
role.default = roles[r][1]
db.session.add(role)
db.session.commit()
def __repr__(self):
return '<Role %r>' % self.name
def __unicode__(self):
return self.name
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), unique=True, index=True)
username = db.Column(db.String(64), unique=True, index=True)
name = db.Column(db.String(64))
role_id = db.Column(db.Integer, db.ForeignKey(Role.id))
password_hash = db.Column(db.String(128))
confirmed = db.Column(db.Boolean, default=False)
about_me = db.Column(db.String(1000))
member_since = db.Column(db.DateTime(), default=datetime.now)
last_seen = db.Column(db.DateTime(), default=datetime.now)
avatar_hash = db.Column(db.String(32))
__mapper_args__ = {'order_by': [confirmed.desc(), id.desc()]}
def __init__(self, **kwargs):
super(User, self).__init__(**kwargs)
if self.role is None:
if self.email == Config.APP_ADMIN:
self.role = Role.query.filter_by(permissions=0xff).first()
if self.role is None:
self.role = Role.query.filter_by(default=True).first()
if self.email is not None and self.avatar_hash is None:
self.avatar_hash = hashlib.md5(
self.email.encode('utf-8')).hexdigest()
@staticmethod
def authenticate(username, password):
"""
验证用户
:param username: 用户名或者电子邮件地址
:param password: 用户密码
"""
user = User.query.filter(db.or_(User.username == username,
User.email == username)).first()
if isinstance(user, User):
if user.verify_password(password):
return None, user
else:
return 'Invalid Password', None
return 'Invalid Username', None
@staticmethod
def make_unique_username(username):
if User.query.filter_by(username=username).first() is None:
return username
version = 2
while True:
new_username = '%s%s' % (username, str(version))
if User.query.filter_by(username=new_username).first() is None:
break
version += 1
return new_username
@property
def password(self):
raise AttributeError('password is not a readable attribute')
@password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)
def verify_password(self, password):
_hash = to_bytes(self.password_hash)
return check_password_hash(_hash, password)
def generate_confirmation_token(self):
s = Serializer(current_app.config['SECRET_KEY'])
return s.dumps({'confirm': self.id})
def confirm(self, token, expiration=3600):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token, max_age=expiration)
except:
return False
if data.get('confirm') != self.id:
return False
self.confirmed = True
db.session.add(self)
db.session.commit()
return True
def generate_reset_token(self):
s = Serializer(current_app.config['SECRET_KEY'])
return s.dumps({'reset': self.id})
def reset_password(self, token, new_password, expiration=3600):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token, max_age=expiration)
except:
return False
if data.get('reset') != self.id:
return False
self.password = new_password
db.session.add(self)
db.session.commit()
return True
def generate_email_change_token(self, new_email):
s = Serializer(current_app.config['SECRET_KEY'])
return s.dumps({'change_email': self.id, 'new_email': new_email})
def change_email(self, token, expiration=3600):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token, max_age=expiration)
except:
return False
if data.get('change_email') != self.id:
return False
new_email = data.get('new_email')
if new_email is None:
return False
if self.query.filter_by(email=new_email).first() is not None:
return False
self.email = new_email
self.avatar_hash = hashlib.md5(
self.email.encode('utf-8')).hexdigest()
db.session.add(self)
db.session.commit()
return True
def can(self, permissions):
return self.role is not None and \
(self.role.permissions & permissions) == permissions
def is_administrator(self):
return self.can(Permission.ADMINISTER) & self.confirmed
def ping(self):
self.last_seen = datetime.now()
db.session.add(self)
db.session.commit()
def gravatar(self, size=100, default='identicon', rating='g'):
if request.is_secure:
url = 'https://secure.gravatar.com/avatar'
else:
url = 'http://www.gravatar.com/avatar'
url = 'https://secure.gravatar.com/avatar'
hash = self.avatar_hash or hashlib.md5(
self.email.encode('utf-8')).hexdigest()
return '{url}/{hash}?s={size}&d={default}&r={rating}'.format(
url=url, hash=hash, size=size, default=default, rating=rating)
def __repr__(self):
return '<User %r>' % (self.name or self.username)
def __unicode__(self):
return self.name or self.username
class AnonymousUser(AnonymousUserMixin):
def can(self, pe
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
Wtxlog是基于Python Flask开发的开源的BLOG/CMS系统,以“简单实用”为目标。 Wtxlog内置栏目、标签(Tags)、文章等主要模型,可以满足绝大部分的内容输出需求。 程序通用性良好,各种云主机、VPS以及应用程序引擎(BAE/JAE/SAE等)均可轻松部署。 ## 主要特性 - 内置模型:栏目、标签、文章、专题、友情链接等 - 数据库:使用SQLAlchemy驱动,主要支持SQLITE和Mysql两种数据库 - 缓存功能:主要支持Memcached和FileSystemCache两种缓存方式 - 编辑器:CKEditor富文本编辑器,Markdown编辑器 - 后台管理:使用Flask-Admin管理后台,功能强大,简单易用 - 换肤功能:可自定义皮肤(主题),语法兼容Jinja2。内置实用的过滤器和上下 文处理器,可实现常用的查询功能。模板设计符合SEO优化理念 - 代码片断:后台增加的代码片断,可在模板文件中直接调用 - 其它功能:Sitemap, Feed, robots.txt, favicon.ico, etc.
资源推荐
资源详情
资源评论
收起资源包目录
基于Python Flask框架的简单的BLOGCMS系统 (546个子文件)
make.bat 6KB
runserver.bat 44B
app.conf 506B
theme.conf 194B
theme.conf 184B
uikit.almost-flat.css 150KB
uikit.css 142KB
bootstrap.css 124KB
bootstrap.min.css 103KB
uikit.almost-flat.min.css 83KB
uikit.min.css 77KB
editor_ie7.css 37KB
editor_iequirks.css 36KB
editor_ie8.css 36KB
editor_ie.css 35KB
editor_gecko.css 34KB
editor.css 34KB
bootstrap-responsive.css 22KB
select2.css 19KB
dialog_ie7.css 17KB
dialog_ie8.css 17KB
bootstrap-responsive.min.css 16KB
dialog_iequirks.css 16KB
dialog_ie.css 16KB
style.css 16KB
dialog_opera.css 16KB
dialog.css 15KB
bootstrap-datetimepicker.css 12KB
codemirror.css 7KB
htmleditor.css 4KB
style.css 3KB
lint.css 3KB
merge.css 3KB
highlight-default.css 2KB
style.css 2KB
htmleditor.min.css 2KB
tern.css 2KB
style.css 2KB
contents.css 2KB
admin.css 2KB
toolbar.css 1KB
wsc.css 1KB
login.css 743B
show-hint.css 662B
rediscli.css 656B
dialog.css 502B
foldgutter.css 435B
upload.css 394B
upload.min.css 134B
fullscreen.css 116B
preview.css 113B
flasky.css_t 9KB
flasky.css_t 5KB
.directory 50B
fontawesome-webfont.eot 55KB
loading.gif 4KB
pattern.gif 4KB
loading.gif 2KB
select2-spinner.gif 2KB
databg.gif 982B
search.gif 782B
headerbg.gif 781B
h2_arrow.gif 761B
nav-bg.gif 273B
licurrent.gif 202B
arrow.gif 176B
li-meta.gif 113B
menubg.gif 66B
spacer.gif 43B
.gitignore 608B
.hgignore 48B
index.html 11KB
layout.html 7KB
editor.html 4KB
article.html 4KB
tmp.html 3KB
layout.html 3KB
index.html 3KB
index.html 2KB
tmpFrameset.html 2KB
article.html 2KB
base.html 2KB
ciframe.html 2KB
article_lists.html 2KB
login.html 1KB
register.html 1KB
reset_password.html 1KB
change_password.html 1KB
change_email.html 1KB
tags.html 1KB
index.html 1KB
article_lists.html 1KB
tags.html 992B
flatpage.html 941B
index.html 808B
topics.html 791B
topic.html 758B
tag.html 742B
category.html 696B
layout.html 693B
共 546 条
- 1
- 2
- 3
- 4
- 5
- 6
资源评论
小蜜蜂vs码农
- 粉丝: 2403
- 资源: 287
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功