From 8255913c58106ab50a6d7af6f2ca0c10920e7891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ku=C5=BE=C3=ADlek?= Date: Wed, 5 Feb 2020 17:12:19 +0100 Subject: [PATCH] Great reorganization, rip flask-admin --- yadc/__init__.py | 23 ++++--- yadc/bp/main.py | 133 ++++---------------------------------- yadc/bp/post.py | 117 +++++++++++++++++++++++++++++++++ yadc/forms.py | 5 +- yadc/models.py | 6 +- yadc/templates/base.html | 5 +- yadc/templates/index.html | 4 +- yadc/templates/post.html | 5 +- yadc/utils.py | 9 ++- 9 files changed, 163 insertions(+), 144 deletions(-) create mode 100644 yadc/bp/post.py diff --git a/yadc/__init__.py b/yadc/__init__.py index 928fa6d..1ad61c0 100644 --- a/yadc/__init__.py +++ b/yadc/__init__.py @@ -6,15 +6,16 @@ from flask_migrate import Migrate from flask_login import LoginManager from flask_assets import Environment as AssetsEnvironment, Bundle as AssetsBundle -from flask_admin import Admin -from flask_admin.contrib.sqla import ModelView +# from flask_admin import Admin +# from flask_admin.contrib.sqla import ModelView db = SQLAlchemy() migrate = Migrate() login = LoginManager() assets = AssetsEnvironment() -admin = Admin() +# THIS FUCKER DARES TO MESS WITH MY BLUEPRINTS (that blueprint collision shitxception) +# admin = Admin() def create_app(): @@ -27,7 +28,7 @@ def create_app(): POST_LIST_THUMB_HEIGHT=200, POST_UPLOADS=os.path.join(app.instance_path, 'post'), INSTANCE_NAME='YADC', - POSTS_PER_PAGE=8, + POSTS_PER_PAGE=4, SQLALCHEMY_ECHO=True, ) @@ -44,17 +45,19 @@ def create_app(): from yadc import models - admin.init_app(app) - admin.add_view(ModelView(models.User, db.session)) - admin.add_view(ModelView(models.Post, db.session)) - admin.add_view(ModelView(models.Tag, db.session)) - admin.add_view(ModelView(models.Comment, db.session)) + # admin.init_app(app) + # admin.add_view(ModelView(models.User, db.session)) + # admin.add_view(ModelView(models.Post, db.session)) + # admin.add_view(ModelView(models.Tag, db.session)) + # admin.add_view(ModelView(models.Comment, db.session)) - from yadc.bp import main, auth + from yadc.bp import main, post, auth app.register_blueprint(main.bp) + app.register_blueprint(post.bp, url_prefix='/post') app.register_blueprint(auth.bp, url_prefix='/user') login.login_view = 'auth.login' + #assets.url = app.static_url_path scss = AssetsBundle('default.scss', filters='libsass', output='all.css') assets.register('scss_all', scss) diff --git a/yadc/bp/main.py b/yadc/bp/main.py index c839d04..61496a5 100644 --- a/yadc/bp/main.py +++ b/yadc/bp/main.py @@ -8,124 +8,15 @@ from PIL import Image from sqlalchemy import func from sqlalchemy.orm import aliased -from werkzeug.urls import Href - from yadc import db from yadc.forms import UploadPostForm -from yadc.models import FILETYPE, RATING, Post, Tag, post_tags - -def query_replace(dic, base=''): - args = request.args.to_dict() - return Href(base)(args.update(dic) or args) +from yadc.models import FILETYPE, RATING, Post, Tag bp = Blueprint('main', __name__) @bp.route('/') def index(): - return redirect(url_for('main.posts')) - -# @bp.route('/') -@bp.route('/post', defaults={'page': 1}) -@bp.route('/post/') -def posts(page): - def tags_prepare(posts): - # tags = db.session.query(Tag, func.array_agg(posts.c.id)).join(posts, Tag.posts).group_by(Tag.id).all() - tags = db.session.query(Tag, func.array_agg(Post.id)).join(Tag.posts).filter(Post.id.in_([p.id for p in posts])).group_by(Tag.id).all() - - # tagset = set() - # taglist = list() - # for post in posts: - # for tag in post.tags: - # tagset.add(tag) - # taglist.append(tag) - # for tag in tagset: - # tag.count = taglist.count(tag) - - for tag,p_ids in tags: - tag.count = len(p_ids) - tag.post_ids = p_ids - tag.endpoint = query_replace({'tags': tag.content.replace(' ','_')}, url_for('main.posts')) - # tags = list(tagset) - tags = [t[0] for t in tags] - tags.sort(key=lambda x: (x.category.value, x.content) ) - return tags - - def parse_args(): - args = request.args - tags = (args.get('tags') or '').split(' ') - tags = [t.replace('_',' ') for t in tags] if tags[0] != '' else [] - rating = {r.name : r for r in RATING}.get(args.get('rating')) or RATING.safe - matched_ratings = [r for r in RATING if r.value<=rating.value] - # page = int(args.get('page') or 1) - return (tags, matched_ratings) - - f_tags, f_rating = parse_args() - posts_query = Post.query - if len(f_tags)>0: - posts_query = posts_query.join(Post.tags).group_by(Post.id).filter(Tag.content.in_(f_tags)).having(func.count(Post.id)==len(f_tags)) - posts_query = posts_query.filter(Post.rating.in_(f_rating)).order_by(Post.created) #.offset((page-1)*posts_on_page).limit(posts_on_page) - - posts = posts_query.paginate(page, app.config.get('POSTS_PER_PAGE')) - tags = tags_prepare(posts.items) - - flash(parse_args()) - # flash(posts.items) - # flash(tags) - - return render_template('index.html', posts=posts.items, tags=tags, pagination=posts, query_replace=query_replace) - -@bp.route('/post/show/') -def post_show(id): - post = Post.query.filter_by(id=id).first() - # flash(post) - - tags_count = db.session.query(Tag, func.count(Post.id)).join(Tag.posts).filter(Post.id==id).join(aliased(Post), Tag.posts).group_by(Tag).all() - - for tag_count in tags_count: - tag, count = tag_count - tag.count = count - tag.endpoint = query_replace({'tags': tag.content.replace(' ','_')}, url_for('main.posts')) - - return render_template('post.html', post=post, tags=post.tags) - - -@bp.route('/post/upload', methods=['GET', 'POST']) -@login_required -def post_upload(): - form = UploadPostForm(request.form) - if request.method == 'POST' and form.validate(): - file = request.files.get(form.post_img.name) - file.data = io.BytesIO(file.read()) - - # tagy - - post = Post(file, source=form.sauce.data, rating=RATING[form.rating.data], author=current_user) - - - with open(post.image_path, "wb") as f: - f.write(file.data.getbuffer()) - # file.seek(0) - # file.save(post.image_path) - - with Image.open(file.data) as im: - im = im.convert('RGB') - - if post.jpeg_path is not None: - im.save(post.jpeg_path, 'JPEG', quality=80) - - im.thumbnail([512,512]) - im.save(post.thumb_path, 'JPEG', quality=80) - - - db.session.add(post) - db.session.commit() - - flash('Successfully submitted {}'.format(str(post))) - - return redirect(url_for('main.post_upload')) - - return render_template('upload.html', form=form) - + return redirect(url_for('post.posts')) @bp.route('/i/') def uploaded_img(path, store='img', exten=None): @@ -147,15 +38,15 @@ def uploaded_thumb(*args, **kwargs): return uploaded_img(*args, **kwargs, store='thumb', exten='jpg') -@bp.route('/threads') -def threads(): - return render_template('index.html') +# @bp.route('/threads') +# def threads(): +# return render_template('index.html') -@bp.route('/user/show/') -def user_profile(username): - pass +# @bp.route('/user/show/') +# def user_profile(username): +# pass -@bp.route('/user/settings') -@login_required -def user_settings(): - pass +# @bp.route('/user/settings') +# @login_required +# def user_settings(): +# pass \ No newline at end of file diff --git a/yadc/bp/post.py b/yadc/bp/post.py new file mode 100644 index 0000000..55b1647 --- /dev/null +++ b/yadc/bp/post.py @@ -0,0 +1,117 @@ +import io +import os + +from flask import (Blueprint, abort, current_app, flash, redirect, + render_template, request, send_from_directory, url_for) +from flask_login import current_user, login_required +from PIL import Image +from sqlalchemy import func +from sqlalchemy.orm import aliased + +from yadc import db +from yadc.forms import UploadPostForm +from yadc.models import FILETYPE, RATING, Post, Tag +from yadc.utils import query_replace + +bp = Blueprint('post', __name__) + +# @bp.route('/') +@bp.route('', defaults={'page': 1}) +@bp.route('/') +def posts(page): + def tags_prepare(posts): + # tags = db.session.query(Tag, func.array_agg(posts.c.id)).join(posts, Tag.posts).group_by(Tag.id).all() + tags = db.session.query(Tag, func.array_agg(Post.id)).join(Tag.posts).filter(Post.id.in_([p.id for p in posts])).group_by(Tag.id).all() + + # tagset = set() + # taglist = list() + # for post in posts: + # for tag in post.tags: + # tagset.add(tag) + # taglist.append(tag) + # for tag in tagset: + # tag.count = taglist.count(tag) + + for tag,p_ids in tags: + tag.count = len(p_ids) + tag.post_ids = p_ids + tag.endpoint = query_replace({'tags': tag.content.replace(' ','_')}, url_for('.posts')) + # tags = list(tagset) + tags = [t[0] for t in tags] + tags.sort(key=lambda x: (x.category.value, x.content) ) + return tags + + def parse_args(): + args = request.args + tags = (args.get('tags') or '').split(' ') + tags = [t.replace('_',' ') for t in tags] if tags[0] != '' else [] + rating = {r.name : r for r in RATING}.get(args.get('rating')) or RATING.safe + matched_ratings = [r for r in RATING if r.value<=rating.value] + # page = int(args.get('page') or 1) + return (tags, matched_ratings) + + f_tags, f_rating = parse_args() + posts_query = Post.query + if len(f_tags)>0: + posts_query = posts_query.join(Post.tags).group_by(Post.id).filter(Tag.content.in_(f_tags)).having(func.count(Post.id)==len(f_tags)) + posts_query = posts_query.filter(Post.rating.in_(f_rating)).order_by(Post.created) #.offset((page-1)*posts_on_page).limit(posts_on_page) + + posts = posts_query.paginate(page, current_app.config.get('POSTS_PER_PAGE')) + tags = tags_prepare(posts.items) + + flash(parse_args()) + # flash(posts.items) + # flash(tags) + + return render_template('index.html', posts=posts.items, tags=tags, pagination=posts, query_replace=query_replace) + +@bp.route('/show/') +def post_show(id): + post = Post.query.filter_by(id=id).first() + # flash(post) + + tags_count = db.session.query(Tag, func.count(Post.id)).join(Tag.posts).filter(Post.id==id).join(aliased(Post), Tag.posts).group_by(Tag).all() + + for tag_count in tags_count: + tag, count = tag_count + tag.count = count + tag.endpoint = query_replace({'tags': tag.content.replace(' ','_')}, url_for('.posts')) + + return render_template('post.html', post=post, tags=post.tags) + +@bp.route('/upload', methods=['GET', 'POST']) +@login_required +def post_upload(): + form = UploadPostForm(request.form) + if request.method == 'POST' and form.validate(): + file = request.files.get(form.post_img.name) + file.data = io.BytesIO(file.read()) + + # tagy + + post = Post(file, source=form.sauce.data, rating=RATING[form.rating.data], author=current_user) + + + with open(post.image_path, "wb") as f: + f.write(file.data.getbuffer()) + # file.seek(0) + # file.save(post.image_path) + + with Image.open(file.data) as im: + im = im.convert('RGB') + + if post.jpeg_path is not None: + im.save(post.jpeg_path, 'JPEG', quality=80) + + im.thumbnail([512,512]) + im.save(post.thumb_path, 'JPEG', quality=80) + + + db.session.add(post) + db.session.commit() + + flash('Successfully submitted {}'.format(str(post))) + + return redirect(url_for('.post_upload')) + + return render_template('upload.html', form=form) diff --git a/yadc/forms.py b/yadc/forms.py index 6e4b9a6..d271314 100644 --- a/yadc/forms.py +++ b/yadc/forms.py @@ -78,4 +78,7 @@ class UploadPostForm(CSRFForm): # Not sure if safe # real_mimetype = Magic(mime=True).from_buffer(file.stream.read()) if client_mimetype not in ['image/png','image/jpeg']: - raise ValidationError('Please select an image file of PNG or JPEG format') \ No newline at end of file + raise ValidationError('Please select an image file of PNG or JPEG format') + + +# class CommentForm(CSRFForm): diff --git a/yadc/models.py b/yadc/models.py index e1549d9..d4e5933 100644 --- a/yadc/models.py +++ b/yadc/models.py @@ -152,7 +152,7 @@ class Post(TimestampMixin, db.Model): @property def image_path(self): filename = "{}.{}".format(self.md5, 'jpg' if self.filetype is FILETYPE.jpeg else 'png') - return os.path.join(current_app.instance_path, 'post', 'img', filename) + return os.path.join(current_app.config.get('POST_UPLOADS'), 'img', filename) @property def jpeg_path(self): @@ -160,12 +160,12 @@ class Post(TimestampMixin, db.Model): return None jpeg_filename = "{}.{}".format(self.md5, 'jpg') - return os.path.join(current_app.instance_path, 'post', 'jpeg', jpeg_filename) + return os.path.join(current_app.config.get('POST_UPLOADS'), 'jpeg', jpeg_filename) @property def thumb_path(self): jpeg_filename = "{}.{}".format(self.md5, 'jpg') - return os.path.join(current_app.instance_path, 'post', 'thumb', jpeg_filename) + return os.path.join(current_app.config.get('POST_UPLOADS'), 'thumb', jpeg_filename) @cached_property def image_resolution(self): diff --git a/yadc/templates/base.html b/yadc/templates/base.html index 8fafdd0..b7b576b 100644 --- a/yadc/templates/base.html +++ b/yadc/templates/base.html @@ -17,9 +17,8 @@ YaDc