Skip to content
This repository has been archived by the owner on Oct 1, 2020. It is now read-only.

Commit

Permalink
Criado carregamento dinâmico das extensões e bluprints
Browse files Browse the repository at this point in the history
Close #5
  • Loading branch information
Riverfount committed Aug 31, 2018
1 parent a611db9 commit 8edd011
Show file tree
Hide file tree
Showing 21 changed files with 393 additions and 0 deletions.
Empty file added build/lib/talkshow/__init__.py
Empty file.
28 changes: 28 additions & 0 deletions build/lib/talkshow/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from flask import Flask

from talkshow.blueprints.restapi import restapi
from talkshow.blueprints.webui import webui
from talkshow.ext import admin
from talkshow.ext import apidocs
from talkshow.ext import bootstrap
from talkshow.ext import cli
from talkshow.ext import configuration
from talkshow.ext import db
from talkshow.ext import login


def create_app():
"""Creates a new Flask app"""
app = Flask(__name__)
configuration.configure(app)
# extensions
db.configure(app) # <-- `app` passado para o db factory
cli.configure(app) # <-- `app` passado para o cli factory
bootstrap.configure(app) # <-- `app` passado para o bootstrap factory
admin.configure(app) # <-- `app` passado para o admin factory
apidocs.configure(app) # <-- `app` passado para o apidocs factory
login.configure(app) # <-- `app` passado para o login factory
# blueprints
webui.configure(app) # <-- registro do webui
restapi.configure(app) # <-- registro do restapi
return app
Empty file.
80 changes: 80 additions & 0 deletions build/lib/talkshow/blueprints/restapi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from flask import Blueprint
from flask import current_app as app
from flask_restful import Api, Resource, reqparse
from flask_simplelogin import login_required

bp = Blueprint('restapi', __name__, url_prefix='/api/v1')
api = Api(bp)


event_post_parser = reqparse.RequestParser()
event_post_parser.add_argument('name', required=True)
event_post_parser.add_argument('date', required=True)


class Event(Resource):
def get(self):
return {'events': list(app.db['events'].find())}

@login_required(basic=True)
def post(self):
"""
Creates new event
---
parameters:
- in: body
name: body
schema:
id: Event
properties:
name:
type: string
date:
type: string
responses:
201:
description: Success or failure message
schema:
properties:
event_created:
type: string
description: The id of the created event
"""
event = event_post_parser.parse_args()
new = app.db['events'].insert({'name': event.name, 'date': event.date})
return {'event_created': new.inserted_id}, 201


proposal_post_parser = reqparse.RequestParser()
proposal_post_parser.add_argument('name', required=True)
proposal_post_parser.add_argument('email', required=True)
proposal_post_parser.add_argument('title', required=True)
proposal_post_parser.add_argument('description', required=True)


class EventItem(Resource):
def get(self, event_id):
event = app.db['events'].find_one({'_id': event_id})
proposals = app.db['proposal'].find({'event_id': event_id})
return {'event': event, 'proposals': list(proposals)}

def post(self, event_id):
event = app.db['events'].find_one({'_id': event_id})
prop = proposal_post_parser.parse_args()
new = app.db['proposal'].insert({
'event_id': event['_id'],
'name': prop.name,
'email': prop.email,
'title': prop.title,
'description': prop.description,
'approved': False
})
return {'proposal created': new.inserted_id}, 201


def configure(app):
"""Initialize API and register blueprint"""
api.add_resource(Event, '/event/')
api.add_resource(EventItem, '/event/<event_id>')

app.register_blueprint(bp)
Empty file.
67 changes: 67 additions & 0 deletions build/lib/talkshow/blueprints/restapi/resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from flask import current_app as app
from flask_restful import reqparse, Resource
from flask_simplelogin import login_required

event_post_parser = reqparse.RequestParser()
event_post_parser.add_argument('name', required=True)
event_post_parser.add_argument('date', required=True)


class Event(Resource):
def get(self):
return {'events': list(app.db['events'].find())}

@login_required(basic=True)
def post(self):
"""
Creates new event
---
parameters:
- in: body
name: body
schema:
id: Event
properties:
name:
type: string
date:
type: string
responses:
201:
description: Success or failure message
schema:
properties:
event_created:
type: string
description: The id of the created event
"""
event = event_post_parser.parse_args()
new = app.db['events'].insert({'name': event.name, 'date': event.date})
return {'event_created': new.inserted_id}, 201


proposal_post_parser = reqparse.RequestParser()
proposal_post_parser.add_argument('name', required=True)
proposal_post_parser.add_argument('email', required=True)
proposal_post_parser.add_argument('title', required=True)
proposal_post_parser.add_argument('description', required=True)


class EventItem(Resource):
def get(self, event_id):
event = app.db['events'].find_one({'_id': event_id})
proposals = app.db['proposal'].find({'event_id': event_id})
return {'event': event, 'proposals': list(proposals)}

def post(self, event_id):
event = app.db['events'].find_one({'_id': event_id})
prop = proposal_post_parser.parse_args()
new = app.db['proposal'].insert({
'event_id': event['_id'],
'name': prop.name,
'email': prop.email,
'title': prop.title,
'description': prop.description,
'approved': False
})
return {'proposal created': new.inserted_id}, 201
15 changes: 15 additions & 0 deletions build/lib/talkshow/blueprints/restapi/restapi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from flask import Blueprint
from flask_restful import Api

from blueprints.restapi.resource import Event, EventItem

bp = Blueprint('restapi', __name__, url_prefix='/api/v1')
api = Api(bp)


def configure(app):
"""Initialize API and register blueprint"""
api.add_resource(Event, '/event/')
api.add_resource(EventItem, '/event/<event_id>')

app.register_blueprint(bp)
Empty file.
31 changes: 31 additions & 0 deletions build/lib/talkshow/blueprints/webui/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from flask import current_app as app, flash
from flask_admin.actions import action
from flask_admin.contrib.pymongo import ModelView

from blueprints.webui.forms import ProposalAdminForm


def format_event(self, request, obj, fieldname, *args, **kwargs):
"""Returns the name for the event (see also get_list)"""
return app.db['events'].find_one({'_id': obj['event_id']})['name']


class AdminProposal(ModelView):
"""The proposal admin item"""
can_create = False
column_list = ('event_id', 'name', 'title', 'approved')
form = ProposalAdminForm
column_formatters = {'event_id': format_event}

@action(
'toggle_approval',
'Approve/Disapprove',
'Approve/Disapprove?'
)
def action_toggle_publish(self, ids):
for _id in ids:
model = self.coll.find_one({'_id': _id})
model['approved'] = not model['approved']
self.coll.update({'_id': _id}, model)

flash(f'{len(ids)} items published/Unpublished.', 'success')
26 changes: 26 additions & 0 deletions build/lib/talkshow/blueprints/webui/froms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import wtforms as wtf
from flask_wtf import FlaskForm


class ProposalForm(FlaskForm):
"""Form to register new proposals to events"""
name = wtf.StringField(
'name', validators=[wtf.validators.DataRequired()]
)
email = wtf.StringField(
'email', validators=[wtf.validators.Email()]
)
title = wtf.StringField(
'title', validators=[wtf.validators.DataRequired()]
)
description = wtf.TextAreaField(
'description', validators=[wtf.validators.DataRequired()]
)
submit = wtf.SubmitField("Enviar")


class ProposalAdminForm(ProposalForm):
"""Extends Proposal form to use in admin interface"""
event_id = wtf.StringField()
approved = wtf.BooleanField()
submit = None
45 changes: 45 additions & 0 deletions build/lib/talkshow/blueprints/webui/webui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import datetime
from flask import Blueprint, request, render_template, abort
from flask import current_app as app

from blueprints.webui.forms import ProposalForm
from blueprints.webui.admin import AdminProposal

bp = Blueprint("webui", __name__)


@bp.route('/')
def index():
"""View to list all registered events"""
events = app.db['events'].find()
return render_template('index.html', events=events)


@bp.route('/<event_id>/', methods=['GET', 'POST'])
def event(event_id):
"""A form to submit a talk to the selected event"""
event = app.db['events'].find_one({'_id': event_id})
if not event:
abort(404, 'Evento não encontrado')

form = ProposalForm(request.form)

if form.validate_on_submit():
# Se estamos no meio de um submit válido preparamos os dados
proposal = form.data.copy()
proposal['event_id'] = event_id
proposal['date'] = datetime.datetime.today().date().isoformat()
proposal['approved'] = False
# e gravamos no banco de dados
app.db['proposal'].insert_one(proposal)

return render_template('thanks.html', proposal=proposal, event=event)

# exibimos o formulário limpo
return render_template('event.html', form=form, event=event)


def configure(app):
"""Register the Blueprint to the app"""
app.register_blueprint(bp)
app.admin.add_view(AdminProposal(app.db['proposal'], 'Proposals'))
Empty file.
14 changes: 14 additions & 0 deletions build/lib/talkshow/ext/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from flask_admin import Admin
from flask_admin.base import AdminIndexView # noqa
from flask_admin.contrib.pymongo import ModelView # noqa

from flask_simplelogin import login_required

# decorate Flask-Admin view via Monkey Patching
AdminIndexView._handle_view = login_required(AdminIndexView._handle_view)
ModelView._handle_view = login_required(ModelView._handle_view)


def configure(app):
"""Adds admin extension to app"""
app.admin = Admin(app, "TalkShow", template_mode="bootstrap2")
6 changes: 6 additions & 0 deletions build/lib/talkshow/ext/apidocs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from flasgger import Flasgger


def configure(app):
"""Starts openapispec"""
Flasgger(app)
6 changes: 6 additions & 0 deletions build/lib/talkshow/ext/bootstrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from flask_bootstrap import Bootstrap


def configure(app):
"""Configures the bootstrap extension"""
Bootstrap(app)
22 changes: 22 additions & 0 deletions build/lib/talkshow/ext/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import click
from talkshow.ext.login import create_user


def configure(app):
"""Attach new commands in to app"""

@app.cli.command()
@click.option('--name', '-n', required=True)
@click.option('--date', '-d', required=True)
def addevent(name, date):
"""Creates a new event entry"""
event = app.db['events'].insert_one({'name': name, 'date': date})
click.echo(f"{event.inserted_id} cadastrado com sucesso!")

@app.cli.command()
@click.option('--username', '-u', required=True)
@click.option('--password', '-p', required=True)
def adduser(username, password):
"""Creates a new admin user"""
user = create_user(username, password)
click.echo(f"{user.inserted_id} cadastrado com sucesso!")
8 changes: 8 additions & 0 deletions build/lib/talkshow/ext/configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from dynaconf import FlaskDynaconf


def configure(app):
""" Initialize Dynaconf Extension
:param app: Instance of flask application
"""
FlaskDynaconf(app)
14 changes: 14 additions & 0 deletions build/lib/talkshow/ext/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pymongo import MongoClient
from tinymongo import TinyMongoClient


def configure(app):
"""Creates a new database connection"""

if app.env == "production":
client = MongoClient(host="localhost")
else:
client = TinyMongoClient('database')

db_name = app.config.get('MONGODB_NAME', 'db')
app.db = client[db_name]
Loading

0 comments on commit 8edd011

Please sign in to comment.