From eb9a593fd50f8fe194f1603e8a10fcca07c3495d Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sat, 4 Jul 2020 15:25:31 +0300 Subject: [PATCH] structure 1 --- .idea/codeStyles/Project.xml | 7 + .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/dictionaries/.xml | 7 + .idea/encodings.xml | 6 + .idea/helloworld_web.iml | 2 +- .idea/misc.xml | 2 +- app/__init__.py | 21 +++ forms.py => app/forms.py | 0 app/models.py | 85 +++++++++++ {templates => app/templates}/admin.html | 0 {templates => app/templates}/contact.html | 0 {templates => app/templates}/index.html | 0 {templates => app/templates}/login.html | 0 app/views.py | 62 ++++++++ config.py | 23 +++ main.py | 178 ---------------------- models.py | 0 runner.py | 31 ++++ 18 files changed, 249 insertions(+), 180 deletions(-) create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/dictionaries/.xml create mode 100644 .idea/encodings.xml create mode 100644 app/__init__.py rename forms.py => app/forms.py (100%) create mode 100644 app/models.py rename {templates => app/templates}/admin.html (100%) rename {templates => app/templates}/contact.html (100%) rename {templates => app/templates}/index.html (100%) rename {templates => app/templates}/login.html (100%) create mode 100644 app/views.py create mode 100644 config.py delete mode 100644 main.py delete mode 100644 models.py create mode 100644 runner.py diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..8550006 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..df5f35d --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dictionaries/.xml b/.idea/dictionaries/.xml new file mode 100644 index 0000000..291ce5b --- /dev/null +++ b/.idea/dictionaries/.xml @@ -0,0 +1,7 @@ + + + + sqlalchemy + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..de8d7f4 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/helloworld_web.iml b/.idea/helloworld_web.iml index 858c4d5..ca5e422 100644 --- a/.idea/helloworld_web.iml +++ b/.idea/helloworld_web.iml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index be8870e..b228a21 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..29ce935 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,21 @@ +from flask import Flask +from flask_migrate import Migrate, MigrateCommand +from flask_sqlalchemy import SQLAlchemy +from flask_script import Manager, Command, Shell +from flask_login import LoginManager +import os, config + +# создание экземпляра приложения +app = Flask(__name__) +app.config.from_object(os.environ.get('FLASK_ENV') or 'config.DevelopementConfig') + +# инициализирует расширения +db = SQLAlchemy(app) +migrate = Migrate(app, db) +login_manager = LoginManager(app) +login_manager.login_view = 'login' + +# import views +from . import views +# from . import forum_views +# from . import admin_views diff --git a/forms.py b/app/forms.py similarity index 100% rename from forms.py rename to app/forms.py diff --git a/app/models.py b/app/models.py new file mode 100644 index 0000000..12bd3ad --- /dev/null +++ b/app/models.py @@ -0,0 +1,85 @@ +from app import db, login_manager +from datetime import datetime +from flask_login import (LoginManager, UserMixin, login_required, + login_user, current_user, logout_user) +from werkzeug.security import generate_password_hash, check_password_hash + + +class Category(db.Model): + __tablename__ = 'categories' + id = db.Column(db.Integer(), primary_key=True) + name = db.Column(db.String(255), nullable=False) + slug = db.Column(db.String(255), nullable=False) + created_on = db.Column(db.DateTime(), default=datetime.utcnow) + posts = db.relationship('Post', backref='category') + + def __repr__(self): + return "<{}:{}>".format(id, self.name) + + +class Post(db.Model): + __tablename__ = 'posts' + id = db.Column(db.Integer(), primary_key=True) + title = db.Column(db.String(255), nullable=False) + slug = db.Column(db.String(255), nullable=False) + content = db.Column(db.Text(), nullable=False) + created_on = db.Column(db.DateTime(), default=datetime.utcnow) + updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) + category_id = db.Column(db.Integer(), db.ForeignKey('categories.id')) + + def __repr__(self): + return "<{}:{}>".format(self.id, self.title[:10]) + + +post_tags = db.Table('post_tags', + db.Column('post_id', db.Integer, db.ForeignKey('posts.id')), + db.Column('tag_id', db.Integer, db.ForeignKey('tags.id')) + ) + + +class Tag(db.Model): + __tablename__ = 'tags' + id = db.Column(db.Integer(), primary_key=True) + name = db.Column(db.String(255), nullable=False) + slug = db.Column(db.String(255), nullable=False) + created_on = db.Column(db.DateTime(), default=datetime.utcnow) + posts = db.relationship('Post', secondary=post_tags, backref='tags') + + def __repr__(self): + return "<{}:{}>".format(id, self.name) + + +class Feedback(db.Model): + __tablename__ = 'feedbacks' + id = db.Column(db.Integer(), primary_key=True) + name = db.Column(db.String(1000), nullable=False) + email = db.Column(db.String(100), nullable=False) + message = db.Column(db.Text(), nullable=False) + created_on = db.Column(db.DateTime(), default=datetime.utcnow) + + def __repr__(self): + return "<{}:{}>".format(self.id, self.name) + + +class User(db.Model, UserMixin): + __tablename__ = 'users' + id = db.Column(db.Integer(), primary_key=True) + name = db.Column(db.String(100)) + username = db.Column(db.String(50), nullable=False, unique=True) + email = db.Column(db.String(100), nullable=False, unique=True) + password_hash = db.Column(db.String(100), nullable=False) + created_on = db.Column(db.DateTime(), default=datetime.utcnow) + updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) + + def __repr__(self): + return "<{}:{}>".format(self.id, self.username) + + def set_password(self, password): + self.password_hash = generate_password_hash(password) + + def check_password(self, password): + return check_password_hash(self.password_hash, password) + +@login_manager.user_loader +def load_user(user_id): + return db.session.query(User).get(user_id) diff --git a/templates/admin.html b/app/templates/admin.html similarity index 100% rename from templates/admin.html rename to app/templates/admin.html diff --git a/templates/contact.html b/app/templates/contact.html similarity index 100% rename from templates/contact.html rename to app/templates/contact.html diff --git a/templates/index.html b/app/templates/index.html similarity index 100% rename from templates/index.html rename to app/templates/index.html diff --git a/templates/login.html b/app/templates/login.html similarity index 100% rename from templates/login.html rename to app/templates/login.html diff --git a/app/views.py b/app/views.py new file mode 100644 index 0000000..42a88e5 --- /dev/null +++ b/app/views.py @@ -0,0 +1,62 @@ +from app import app +from flask import render_template, request, redirect, url_for, flash +from flask_login import login_required, login_user,current_user, logout_user +from .models import User, Post, Category, Feedback, db +from .forms import ContactForm, LoginForm + + +@app.route('/admin/') +@login_required +def admin(): + return render_template('admin.html') + + +@app.route('/') +def index(): + return render_template('index.html') + + +@app.route('/login/', methods=['post', 'get']) +def login(): + if current_user.is_authenticated: + return redirect(url_for('admin')) + form = LoginForm() + if form.validate_on_submit(): + user = db.session.query(User).filter(User.username == form.username.data).first() + if user and user.check_password(form.password.data): + login_user(user, remember=form.remember.data) + nextpage = request.args.get('next', url_for('admin')) + return redirect(nextpage) + else: + flash("Invalid username/password", 'error') + return render_template('login.html', form=form) + + +@app.route('/logout/') +@login_required +def logout(): + logout_user() + flash("You have been logged out.") + return redirect(url_for('login')) + + +@app.route('/contact/', methods=['get', 'post']) +def contact(): + form = ContactForm() + if form.validate_on_submit(): + name = form.name.data + email = form.email.data + message = form.message.data + print(name) + print(email) + print(message) + # здесь логика базы данных + feedback = Feedback(name=name, email=email, message=message) + db.session.add(feedback) + db.session.commit() + + print("\nData received. Now redirecting ...") + flash("Message Received", "success") + return redirect(url_for('contact')) + + return render_template('contact.html', form=form) diff --git a/config.py b/config.py new file mode 100644 index 0000000..db1c4a8 --- /dev/null +++ b/config.py @@ -0,0 +1,23 @@ +import os + +app_dir = os.path.abspath(os.path.dirname(__file__)) + + +class BaseConfig: + SECRET_KEY = os.environ.get('SECRET_KEY') or '0d6e368e-bd0c-11ea-921d-9342d47f60ca' + SQLALCHEMY_TRACK_MODIFICATIONS = False + + +class DevelopementConfig(BaseConfig): + DEBUG = True + SQLALCHEMY_DATABASE_URI = 'sqlite:///db.sqlite' + + +class TestingConfig(BaseConfig): + DEBUG = True + SQLALCHEMY_DATABASE_URI = 'sqlite:///db.sqlite' + + +class ProductionConfig(BaseConfig): + DEBUG = False + SQLALCHEMY_DATABASE_URI = 'sqlite:///db.sqlite' diff --git a/main.py b/main.py deleted file mode 100644 index 9b1b5c1..0000000 --- a/main.py +++ /dev/null @@ -1,178 +0,0 @@ -import flask -from flask import Flask, request, current_app, url_for, render_template, flash, redirect -from werkzeug.security import generate_password_hash, check_password_hash -from flask_script import Manager, Shell -from flask_migrate import Migrate, MigrateCommand -from flask_login import LoginManager, UserMixin, login_required, login_user, current_user, logout_user -from jinja2 import Template -from flask_sqlalchemy import SQLAlchemy -from datetime import datetime - -from forms import ContactForm, LoginForm - -app = Flask(__name__) -app.debug = True -app.config['SECRET_KEY'] = '0d6e368e-bd0c-11ea-921d-9342d47f60ca' -app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False -app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///db.sqlite" -db = SQLAlchemy(app) -login_manager = LoginManager(app) -login_manager.login_view = 'login' -migrate = Migrate(app, db) -manager = Manager(app) -manager.add_command('db', MigrateCommand) - - -class Category(db.Model): - __tablename__ = 'categories' - id = db.Column(db.Integer(), primary_key=True) - name = db.Column(db.String(255), nullable=False) - slug = db.Column(db.String(255), nullable=False) - created_on = db.Column(db.DateTime(), default=datetime.utcnow) - posts = db.relationship('Post', backref='category') - - def __repr__(self): - return "<{}:{}>".format(id, self.name) - - -class Post(db.Model): - __tablename__ = 'posts' - id = db.Column(db.Integer(), primary_key=True) - title = db.Column(db.String(255), nullable=False) - slug = db.Column(db.String(255), nullable=False) - content = db.Column(db.Text(), nullable=False) - created_on = db.Column(db.DateTime(), default=datetime.utcnow) - updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) - category_id = db.Column(db.Integer(), db.ForeignKey('categories.id')) - - def __repr__(self): - return "<{}:{}>".format(self.id, self.title[:10]) - - -post_tags = db.Table('post_tags', - db.Column('post_id', db.Integer, db.ForeignKey('posts.id')), - db.Column('tag_id', db.Integer, db.ForeignKey('tags.id')) - ) - - -class Tag(db.Model): - __tablename__ = 'tags' - id = db.Column(db.Integer(), primary_key=True) - name = db.Column(db.String(255), nullable=False) - slug = db.Column(db.String(255), nullable=False) - created_on = db.Column(db.DateTime(), default=datetime.utcnow) - posts = db.relationship('Post', secondary=post_tags, backref='tags') - - def __repr__(self): - return "<{}:{}>".format(id, self.name) - - -class Feedback(db.Model): - __tablename__ = 'feedbacks' - id = db.Column(db.Integer(), primary_key=True) - name = db.Column(db.String(1000), nullable=False) - email = db.Column(db.String(100), nullable=False) - message = db.Column(db.Text(), nullable=False) - created_on = db.Column(db.DateTime(), default=datetime.utcnow) - - def __repr__(self): - return "<{}:{}>".format(self.id, self.name) - - -class User(db.Model, UserMixin): - __tablename__ = 'users' - id = db.Column(db.Integer(), primary_key=True) - name = db.Column(db.String(100)) - username = db.Column(db.String(50), nullable=False, unique=True) - email = db.Column(db.String(100), nullable=False, unique=True) - password_hash = db.Column(db.String(100), nullable=False) - created_on = db.Column(db.DateTime(), default=datetime.utcnow) - updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) - - def __repr__(self): - return "<{}:{}>".format(self.id, self.username) - - def set_password(self, password): - self.password_hash = generate_password_hash(password) - - def check_password(self, password): - return check_password_hash(self.password_hash, password) - - -@login_manager.user_loader -def load_user(user_id): - return db.session.query(User).get(user_id) - - -@app.route('/admin/') -@login_required -def admin(): - return render_template('admin.html') - - -@manager.command -def faker(): - print("Команда для добавления поддельных данных в таблицы") - - -@app.route('/') -def index(): - return render_template('index.html') - - -@app.route('/login/', methods=['post', 'get']) -def login(): - if current_user.is_authenticated: - return redirect(url_for('admin')) - form = LoginForm() - if form.validate_on_submit(): - user = db.session.query(User).filter(User.username == form.username.data).first() - if user and user.check_password(form.password.data): - login_user(user, remember=form.remember.data) - nextpage = request.args.get('next', url_for('admin')) - return redirect(nextpage) - else: - flash("Invalid username/password", 'error') - return render_template('login.html', form=form) - - -@app.route('/logout/') -@login_required -def logout(): - logout_user() - flash("You have been logged out.") - return redirect(url_for('login')) - -@app.route('/contact/', methods=['get', 'post']) -def contact(): - form = ContactForm() - if form.validate_on_submit(): - name = form.name.data - email = form.email.data - message = form.message.data - print(name) - print(email) - print(message) - # здесь логика базы данных - feedback = Feedback(name=name, email=email, message=message) - db.session.add(feedback) - db.session.commit() - - print("\nData received. Now redirecting ...") - flash("Message Received", "success") - return redirect(url_for('contact')) - - return render_template('contact.html', form=form) - - -def shell_context(): - import os, sys - return {'app': app, 'os': os, 'sys': sys, 'flask': flask, 'request': request, 'current_app': current_app, - 'url_for': url_for, 'Template': Template, 'db': db} - - -manager.add_command("shell", Shell(make_context=shell_context)) - -if __name__ == "__main__": - db.init_app(app) - manager.run() diff --git a/models.py b/models.py deleted file mode 100644 index e69de29..0000000 diff --git a/runner.py b/runner.py new file mode 100644 index 0000000..aae9f44 --- /dev/null +++ b/runner.py @@ -0,0 +1,31 @@ +import os + +import flask +from flask import request, current_app, url_for +from jinja2 import Template + +from app import app, db +from app.models import User, Post, Tag, Category, Feedback +from flask_script import Manager, Shell +from flask_migrate import MigrateCommand + +manager = Manager(app) + + +@manager.command +def faker(): + print("Команда для добавления поддельных данных в таблицы") + + +def shell_context(): + import sys + return {'app': app, 'os': os, 'sys': sys, 'flask': flask, 'request': request, 'current_app': current_app, + 'url_for': url_for, 'Template': Template, 'db': db, 'User': User, 'Post': Post, 'Tag': Tag, + 'Category': Category, 'Feedback': Feedback} + + +manager.add_command("shell", Shell(make_context=shell_context)) +manager.add_command('db', MigrateCommand) + +if __name__ == '__main__': + manager.run()