import hashlib
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from flask_admin import Admin, AdminIndexView
from flask_security import RoleMixin, SQLAlchemyUserDatastore, current_user, Security
from flask_admin.contrib.sqla import ModelView
from flask_login import UserMixin, login_user, login_required, logout_user, LoginManager
from werkzeug.security import check_password_hash, generate_password_hash
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SECRET_KEY'] = 'my secret is good food'
app.config['SECURITY_PASSWORD_SALT'] = 'moon909'
app.config['SECURITY_PASSWORD_HASH'] = 'sha512_crypt'
db = SQLAlchemy(app)
db.create_all()
manager = LoginManager(app)
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
intro = db.Column(db.String(300), nullable=False)
text = db.Column(db.Text(300), nullable=False)
date = db.Column(db.DateTime(300), default=datetime.utcnow)
def __repr__(self):
return '<Article %r>' % self.id
roles_users = db.Table('roles_users', db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
class User (db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(128), unique=True, nullable=False)
login = db.Column(db.String(128), unique=True, nullable=False)
password = db.Column(db.String(255), nullable=False)
active = db.Column(db.Boolean())
roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users'), lazy='dynamic')
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(100), unique=True)
description = db.Column(db.String(255))
#class AdminView(ModelView):
#def is_accessible(self):
#return current_user.has_role('admin')
#def inaccessible_callback(self, name, **kwargs):
#return redirect(url_for('security.login', next=request.url))
#class HomeAdminView(AdminIndexView):
#def is_accessible(self):
#return current_user.has_role('admin')
#def inaccessible_callback(self, name, **kwargs):
#return redirect(url_for('security.login', next=request.url))
admin = Admin(app) #'FlaskApp', url='/home', index_view=HomeAdminView(name='Home'))
admin.add_view(ModelView(Article, db.session))
admin.add_view(ModelView(User, db.session))
admin.add_view(ModelView(Role, db.session))
#Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
@manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
@app.route('/')
@app.route('/home')
def home():
return render_template("home.html")
@app.route('/news')
def news():
return render_template("news.html")
@app.route('/learning')
def learning():
return render_template("learning.html")
@app.route('/profiles')
def profiles():
return render_template("profiles.html")
@app.route('/article')
def article():
articles = Article.query.order_by(Article.date.desc()).all()
return render_template("article.html", articles=articles)
@app.route('/article/<int:id>')
def post_detail(id):
article = Article.query.get(id)
return render_template("article_detail.html", article=article)
@app.route('/article/<int:id>/update', methods=['POST', 'GET'])
@login_required
def post_update(id):
article = Article.query.get(id)
if request.method == 'POST':
article.title = request.form['title']
article.intro = request.form['intro']
article.text = request.form['text']
try:
db.session.commit()
return redirect('/article')
except:
return "При редактировании статьи произошла ошибка"
else:
return render_template("article_update.html", article=article)
@app.route('/posts', methods=['POST', 'GET'])
@login_required
def create_posts():
if request.method == "POST":
title = request.form['title']
intro = request.form['intro']
text = request.form['text']
article = Article(title=title, intro=intro, text=text)
try:
db.session.add(article)
db.session.commit()
return redirect('/article')
except:
return "При добавлении статьи произошла ошибка"
return render_template("posts.html")
@app.route('/login2', methods=['GET', 'POST'])
def login_page():
email = request.form.get('email')
password = request.form.get('password')
if email and password:
user = User.query.filter_by(email=email).first()
if user and check_password_hash(user.password, password):
login_user(user)
return render_template('home.html')
else:
flash('Login or password is not correct')
else:
flash('Please fill login and password fields')
return render_template('login.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
login = request.form.get('login')
email = request.form.get('email')
password = request.form.get('password')
password2 = request.form.get('password2')
if request.method == 'POST':
if not (login or email or password or password2):
flash('Please, fill all fields!')
elif password != password2:
flash('Passwords are not equal!')
else:
hash_pwd = generate_password_hash(password)
new_user = User(login=login, email=email, password=hash_pwd)
db.session.add(new_user)
db.session.commit()
return redirect(url_for('login_page'))
return render_template('register.html')
@app.route('/logout', methods=['GET', 'POST'])
@login_required
def logout():
logout_user()
return redirect(url_for('home'))
@app.after_request
def redirect_to_login(response):
if response.status_code == 401:
return redirect(url_for('login_page') + '?next=' + request.url)
return response
if __name__ == '__main__':
app.run(debug=True)