Example #1
0
def setup_app():
    app = Bottle()
    app.config.update(config.APP_CONFIG)
    setup_routing(app)
    setup_db(app)
    bottle.app.push(app)
    app = SessionMiddleware(app, config.SESSION_OPTS)
    return app
Example #2
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)
    cors = CORS(app)

    @app.route('/')
    # @requires_auth()
    def greeting():
        """Routes user to a welcome page."""

        return render_template('home.html')
        # return 'Welcome to Magic: The Gathering API'

    @app.route('/contact')
    def contact_page():
        """Routes user to contact info page."""

        return render_template('contact.html')

    # @app.route('/decks')
    # @requires_auth('get:decks')
    # def get_decks():
    #     """
    #     Displays all the decks.
    #     An mtg_browser or mtg_publisher role is needed.
    #     """

    #     decks = Deck.query.all()
    #     decks_readable = [
    #         f'{deck.title} by {deck.creator}' for deck in decks]

    #     return jsonify(decks_readable)

    # @app.route('/cards')
    # @requires_auth('get:cards')
    # def get_cards():
    #     """
    #     Displays all the cards.
    #     An mtg_browser or mtg_publisher role is needed.
    #     """

    #     cards = Card.query.all()
    #     cards_readable = [
    #         f'{card.name}' for card in cards]

    #     return jsonify(cards_readable)

    # @app.route('/cards', methods=['post'])
    # @requires_auth('post:cards')
    # def post_card():
    #     """
    #     Allows a user to post a new card to the database.

    #     The user must supply a JSON body in their post request as well as a
    #     valid JWT in the header. The JSON body must contain "name" and
    #     "type", and it can optionally contain "colors" and "cmc".
    #     An mtg_publisher role is needed.
    #     """

    #     data = json.loads(request.data)
    #     name = data.get('name')
    #     type = data.get('type')
    #     colors = data.get('colors')
    #     cmc = data.get('cmc')

    #     try:
    #         new_card = Card(name, type, colors, cmc)
    #         new_card.insert()
    #     except Exception as e:
    #         print('There was an exception:')
    #         print(e)
    #         abort(422)

    #     return jsonify('posted card successfully')

    # @app.route('/cards/<int:id>', methods=['patch'])
    # @requires_auth('patch:cards')
    # def update_card(id):
    #     """
    #     Allows a user to patch an existing card in the database.

    #     The user must indicate which card they want to edit by providing an id.
    #     They must also supply a JSON body in their patch request as well as a
    #     valid JWT in the header. The JSON body should contain key:value pairs
    #     for the card attribtutes the user would like to update.
    #     An mtg_publisher role is needed.
    #     """

    #     try:
    #         working_card = Card.query.get(id)
    #         test = working_card.id
    #     except Exception as e:
    #         print(f'There was an exception:\n{e}')
    #         abort(404)

    #     try:
    #         data = json.loads(request.data)
    #         name = data.get('name')
    #         type = data.get('type')
    #         colors = data.get('colors')
    #         cmc = data.get('cmc')
    #     except Exception as e:
    #         print(f'There was an exception:\n{e}')
    #         abort(400)

    #     try:
    #         if name:
    #             working_card.name = name
    #         if type:
    #             working_card.type = type
    #         if colors:
    #             working_card.colors = colors
    #         if cmc:
    #             working_card.cmc = cmc
    #         working_card.update()
    #     except Exception as e:
    #         print(f'There was an exception:\n{e}')
    #         abort(422)

    #     return f"""
    #     updated card successfully: {working_card.name} -
    #     {working_card.type} - {working_card.colors} -
    #     {working_card.cmc}
    #     """

    # @app.route('/cards/<int:id>', methods=['delete'])
    # @requires_auth('delete:cards')
    # def delete_card(id):
    #     """
    #     Allows a user to delete a card from the database.

    #     The user must indicate which card they want to delete by providing
    #     an id. They must also supply a valid JWT in the header.
    #     An mtg_publisher role is needed.
    #     """

    #     try:
    #         working_card = Card.query.get(id)
    #         test = working_card.id
    #     except Exception as e:
    #         print(f'There was an exception:\n{e}')
    #         abort(404)

    #     try:
    #         working_card.delete()
    #     except Exception as e:
    #         print(f'There was an exception:\n{e}')
    #         abort(422)

    #     return f"""
    #     deleted card successfully:
    #     {working_card.id} - {working_card.name}
    #     """

    # # Error Handling

    # @app.errorhandler(400)
    # def bad_request(error):
    #     return jsonify({
    #         "success": False,
    #         "error": 400,
    #         "message": "the client sent a bad request"
    #     }), 400

    # @app.errorhandler(401)
    # def unauthorized(error):
    #     return jsonify({
    #         "success": False,
    #         "error": 401,
    #         "message": "user is not authorized to access this resource"
    #     }), 401

    # @app.errorhandler(404)
    # def resource_not_found(error):
    #     return jsonify({
    #         "success": False,
    #         "error": 404,
    #         "message": "resource not found"
    #     }), 404

    # @app.errorhandler(405)
    # def method_not_allowed(error):
    #     return jsonify({
    #         "success": False,
    #         "error": 405,
    #         "message": "the request method is not allowed on this resource"
    #     }), 405

    # @app.errorhandler(422)
    # def unprocessable(error):
    #     return jsonify({
    #         "success": False,
    #         "error": 422,
    #         "message": "the request was unprocessable"
    #     }), 422

    return app
Example #3
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)
    CORS(app, resources={r"/*": {'origins': '*'}})

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type, Authorization, true')
        response.headers.add('Access-Control-Allow-Headers',
                             'GET, PATCH, POST, DELETE, OPTIONS')
        return response

    @app.route('/')
    def index():
        return redirect(LOGIN_URI, 302)

    @app.route('/welcome')
    def welcome():
        return jsonify({
            'success': True,
            'message': 'Login was successful, welcome!'
        })

    ###############################
    # trainers related end-points #
    ###############################
    @app.route('/trainers', methods=['GET'])
    @requires_auth('get:trainers')
    def get_trainers():
        if request.get_json():
            abort(405)

        try:
            trainers = Trainer.query.all()
            if trainers is None:
                raise AuthError(
                    {
                        'code': 'no_trainers',
                        'description': 'There are no trainers on system yet.'
                    }, 404)
        except AuthError as e:
            abort(e.status_code, e.error)

        trainers_formatted = []

        for trainer in trainers:
            trainers_formatted.append(trainer.format())

        return jsonify({'success': True, 'trainers': trainers_formatted})

    @app.route('/trainers', methods=['POST'])
    @requires_auth('post:trainers')
    def add_trainer():
        request_data = request.get_json()

        try:
            if len(request_data) > 3:
                raise AuthError(
                    {
                        'description':
                        'Please include only the name, gender, and age of trainer.'
                    }, 400)
            if not request_data['name']:
                raise AuthError({'description': 'Trainer name is missing.'},
                                400)
            if not request_data['gender']:
                raise AuthError({'description': 'Trainer gender is missing.'},
                                400)
            if not request_data['age']:
                raise AuthError({'description': 'Trainer age is missing.'},
                                400)
        except AuthError as e:
            abort(e.status_code, e.error)

        new_trainer = Trainer()
        new_trainer.name = request_data['name']
        new_trainer.gender = request_data['gender']
        new_trainer.age = request_data['age']

        new_trainer.insert()

        return jsonify({'success': True, 'new_trainer': new_trainer.format()})

    @app.route('/trainers/<id>', methods=['DELETE'])
    @requires_auth('delete:trainers')
    def delete_trainer(id):
        try:
            target_trainer = Trainer.query.filter_by(id=id).first()
            if target_trainer is None:
                raise AuthError(
                    {
                        'code':
                        'trainer_not_found',
                        'description':
                        'There is no trainer with the reuqested id to delete.'
                    }, 404)
        except AuthError as e:
            abort(e.status_code, e.error)

        target_trainer.delete()

        return jsonify({
            'success': True,
            'deleted_trainer': target_trainer.format()
        })

    @app.route('/trainers/<id>', methods=['PATCH'])
    @requires_auth('patch:trainers')
    def patch_trainer(id):
        request_data = request.get_json()

        try:
            target_trainer = Trainer.query.filter_by(id=id).first()
            if target_trainer is None:
                raise AuthError(
                    {
                        'code':
                        'trainer_not_found',
                        'description':
                        'There is no trainer with the reuqested id to modify.'
                    }, 404)
        except AuthError as e:
            abort(e.status_code, e.error)

        if 'name' in request_data:
            target_trainer.name = request_data['name']
        if 'gender' in request_data:
            target_trainer.gender = request_data['gender']
        if 'age' in request_data:
            target_trainer.age = request_data['age']

        target_trainer.update()

        return jsonify({
            'success': True,
            'modified_trainer': target_trainer.format()
        })

    ##############################
    # clients related end-points #
    ##############################
    @app.route('/clients', methods=['GET'])
    @requires_auth('get:clients')
    def get_clients():
        if request.get_json():
            abort(405)

        try:
            clients = Client.query.all()
            if clients is None:
                raise AuthError(
                    {
                        'code': 'no_clients',
                        'description': 'There are no clients on system yet.'
                    }, 404)
        except AuthError as e:
            abort(e.status_code, e.error)

        clients_formatted = []

        for client in clients:
            clients_formatted.append(client.format())

        return jsonify({'success': True, 'clients': clients_formatted})

    @app.route('/clients', methods=['POST'])
    @requires_auth('post:clients')
    def add_client():
        request_data = request.get_json()

        try:
            if len(request_data) > 3:
                raise AuthError(
                    {
                        'description':
                        'Please include only the name, gender, and age of client.'
                    }, 400)
            if not request_data['name']:
                raise AuthError({'description': 'Client name is missing.'},
                                400)
            if not request_data['gender']:
                raise AuthError({'description': 'Client gender is missing.'},
                                400)
            if not request_data['age']:
                raise AuthError({'description': 'Client age is missing.'}, 400)
        except AuthError as e:
            abort(e.status_code, e.error)

        new_client = Client()
        new_client.name = request_data['name']
        new_client.gender = request_data['gender']
        new_client.age = request_data['age']

        new_client.insert()

        return jsonify({'success': True, 'new_client': new_client.format()})

    @app.route('/clients/<id>', methods=['DELETE'])
    @requires_auth('delete:clients')
    def delete_client(id):
        try:
            target_client = Client.query.filter_by(id=id).first()
            if target_client is None:
                raise AuthError(
                    {
                        'code':
                        'client_not_found',
                        'description':
                        'There is no client with the reuqested id to delete.'
                    }, 404)
        except AuthError as e:
            abort(e.status_code, e.error)

        target_client.delete()

        return jsonify({
            'success': True,
            'deleted_client': target_client.format()
        })

    @app.route('/clients/<id>', methods=['PATCH'])
    @requires_auth('patch:clients')
    def patch_client(id):
        request_data = request.get_json()

        try:
            target_client = Client.query.filter_by(id=id).first()
            if target_client is None:
                raise AuthError(
                    {
                        'code':
                        'client_not_found',
                        'description':
                        'There is no client with the reuqested id to modify.'
                    }, 404)
        except AuthError as e:
            abort(e.status_code, e.error)

        if 'name' in request_data:
            target_client.name = request_data['name']
        if 'gender' in request_data:
            target_client.gender = request_data['gender']
        if 'age' in request_data:
            target_client.age = request_data['age']

        target_client.update()

        return jsonify({
            'success': True,
            'modified_client': target_client.format()
        })

    ###############################
    # sessions related end-points #
    ###############################
    @app.route('/sessions', methods=['GET'])
    @requires_auth('get:sessions')
    def get_sessions():
        if request.get_json():
            abort(405)

        try:
            sessions = Session.query.all()
            if sessions is None:
                raise AuthError(
                    {
                        'code': 'no_sessions',
                        'description': 'There are no sessions on system yet.'
                    }, 404)
        except AuthError as e:
            abort(e.status_code, e.error)

        sessions_formatted = []

        for session in sessions:
            sessions_formatted.append(session.format())

        return jsonify({'success': True, 'sessions': sessions_formatted})

    @app.route('/sessions', methods=['POST'])
    @requires_auth('post:sessions')
    def add_session():
        request_data = request.get_json()

        try:
            if len(request_data) > 3:
                raise AuthError(
                    {
                        'description':
                        'Please include only the name, trainer_id, and client_id of the session.'
                    }, 400)
            if not request_data['name']:
                raise AuthError({'description': 'Session name is missing.'},
                                400)
            if not request_data['trainer_id']:
                raise AuthError(
                    {'description': 'Session trainer id is missing.'}, 400)
            if not request_data['client_id']:
                raise AuthError(
                    {'description': 'Session client id is missing.'}, 400)
        except AuthError as e:
            abort(e.status_code, e.error)

        new_session = Session()
        new_session.name = request_data['name']
        new_session.trainer_id = request_data['trainer_id']
        new_session.client_id = request_data['client_id']

        new_session.insert()

        return jsonify({'success': True, 'new_session': new_session.format()})

    @app.route('/sessions/<id>', methods=['DELETE'])
    @requires_auth('delete:sessions')
    def delete_session(id):
        try:
            target_session = Session.query.filter_by(id=id).first()
            if target_session is None:
                raise AuthError(
                    {
                        'code':
                        'session_not_found',
                        'description':
                        'There is no session with the reuqested id to delete.'
                    }, 404)
        except AuthError as e:
            abort(e.status_code, e.error)

        target_session.delete()

        return jsonify({
            'success': True,
            'deleted_session': target_session.format()
        })

    @app.route('/sessions/<id>', methods=['PATCH'])
    @requires_auth('patch:sessions')
    def patch_session(id):
        request_data = request.get_json()

        try:
            target_session = Session.query.filter_by(id=id).first()
            if target_session is None:
                raise AuthError(
                    {
                        'code':
                        'session_not_found',
                        'description':
                        'There is no session with the reuqested id to modify.'
                    }, 404)
        except AuthError as e:
            abort(e.status_code, e.error)

        if 'name' in request_data:
            target_session.name = request_data['name']
        if 'trainer_id' in request_data:
            target_session.trainer_id = request_data['trainer_id']
        if 'client_id' in request_data:
            target_session.client_id = request_data['client_id']

        target_session.update()

        return jsonify({
            'success': True,
            'modified_session': target_session.format()
        })

    ##################
    # error handling #
    ##################
    @app.errorhandler(400)
    def authError_bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": error.description
        }), 400

    @app.errorhandler(401)
    def authError_unauthorized(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": error.description
        }), 401

    @app.errorhandler(404)
    def authError_not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": error.description
        }), 404

    @app.errorhandler(405)
    def method_not_allowed(error):
        return jsonify({
            "success": False,
            "error": 405,
            "message": "method not allowed"
        }), 405

    return app
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)

    CORS(app, resources={r"/api/*": {"origins": "*"}})

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,POST,DELETE,OPTIONS,PUT')
        return response

    @app.route('/categories', methods=['GET'])
    def get_categories():
        categories = Category.query.all()
        formatted_categories = [category.format() for category in categories]
        return jsonify({
            'success': True,
            'categories': formatted_categories,
            'total_categories': len(categories)
        })

    @app.route('/questions', methods=['GET'])
    def get_questions():
        page = request.args.get('page', 1, type=int)
        start = (page - 1) * QUESTIONS_PER_PAGE
        end = start + QUESTIONS_PER_PAGE
        questions = Question.query.all()
        formatted_questions = [question.format() for question in questions]
        categories = Category.query.all()
        formatted_categories = [category.format() for category in categories]
        return jsonify({
            'success': True,
            'questions': formatted_questions[start:end],
            'total_questions': len(questions),
            'categories': formatted_categories
        })

    @app.route('/questions/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):
        question = Question.query.filter(
            Question.id == question_id).one_or_none()
        if question is None:
            abort(404)
        question.delete()
        questions = Question.query.all()
        return jsonify({
            'success':
            True,
            'deleted':
            question_id,
            'questions': [question.format() for question in questions]
        })

    @app.route('/questions', methods=['POST'])
    def create_question():
        body = request.get_json()
        if (body.get("searchTerm")):
            search_term = body.get("searchTerm")
            temp = Question.query.filter(
                Question.question.ilike(f'%{search_term}%')).all()
            questions = [t.format() for t in temp]
            if (len(temp) == 0):
                abort(404)
            return jsonify({
                'success': True,
                'questions': questions,
                'total_questions': len(temp),
                'current_category': 1
            })
        else:
            new_question = body.get("question", None)
            new_category = body.get("category", None)
            new_answer = body.get("answer", None)
            new_difficulty = body.get("difficulty", None)
            try:
                question = Question(question=new_question,
                                    answer=new_answer,
                                    category=new_category,
                                    difficulty=new_difficulty)
                question.insert()
            except:
                abort(422)
            questions = Question.query.all()
            formatted_questions = [qst.format() for qst in questions]
            return jsonify({
                'success': True,
                'questions': formatted_questions,
                'total_questions': len(questions)
            })

    @app.route('/categories/<int:category_id>/questions', methods=['GET'])
    def get_questions_by_category(category_id):
        category = Category.query.filter(
            Category.id == category_id).one_or_none()
        if (category is None):
            abort(404)
        questions = Question.query.filter(
            Question.category == category.id).all()
        formatted_questions = [question.format() for question in questions]
        return jsonify({
            'success': True,
            'category': category.id,
            'questions': formatted_questions,
            'total_questions': len(questions)
        })

    @app.route('/quizzes', methods=['POST'])
    def play_quiz():
        body = request.get_json()
        previous_question = body.get('previous_questions')
        category = body.get('quiz_category')
        if ((category is None) or (previous_question is None)):
            abort(404)

        if (category["type"] == "click"):
            questions = Question.query.all()
        else:
            category_id = int(category["id"]) + 1
            questions = Question.query.filter(
                Question.category == category_id).all()

        random_question = random.choice(questions)

        def is_used(question):
            used = False
            if question.id in previous_question:
                used = True
            return used

        if (len(previous_question) == len(questions)):
            return jsonify({
                'success': True,
                'question': None,
                'previous_questions': previous_question
            })
        while (is_used(random_question)):
            random_question = random.choice(questions)

        return jsonify({
            'success': True,
            'question': random_question.format(),
            'previous_questions': previous_question
        })

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "Bad Request"
        }), 400

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(500)
    def internal_server_error(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "500 Internal Server Error” "
        }), 500

    @app.route('/')
    def hello():
        return jsonify({'success': True})

    return app
Example #5
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)
    '''
  #124 Set up CORS. Allow '*' for origins. Delete the sample route after completing the TODOs
  '''
    cors = CORS(app)
    '''
  Use the after_request decorator to set Access-Control-Allow
  '''
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type, Authorization, true')
        response.headers.add('Access-Control-Methods',
                             'GET,PATCH,POST,DELETE,OPTIONS')

        return response

    '''
  Create an endpoint to handle GET requests 
  for all available categories.
  '''

    @app.route('/categories', methods=['GET'])
    def retrieve_categories():
        categories = Category.query.order_by(Category.type).all()

        if len(categories) == 0:
            abort(404)

        return jsonify({
            'success': True,
            'categories':
            {category.id: category.type
             for category in categories}
        })

    '''
  Create an endpoint to handle GET requests for questions, 
  including pagination (every 10 questions). 
  This endpoint should return a list of questions, 
  number of total questions, current category, categories. 

   TEST: At this point, when you start the application
  you should see questions and categories generated,
  ten questions per page and pagination at the bottom of the screen for three pages.
  Clicking on the page numbers should update the questions. 
  '''

    @app.route('/questions', methods=['GET'])
    def retrieve_questions():
        selection = Question.query.order_by(Question.id).all()
        current_questions = paginate_questions(request, selection)

        categories = Category.query.order_by(Category.type).all()

        if len(current_questions) == 0:
            abort(404)

        return jsonify({
            'success': True,
            'questions': current_questions,
            'total_questions': len(Question.query.all()),
            'categories':
            {category.id: category.type
             for category in categories},
            'current_category': None
        })

    '''
  Create an endpoint to DELETE question using a question ID. 

  TEST: When you click the trash icon next to a question, the question will be removed.
  This removal will persist in the database and when you refresh the page. 
  '''

    @app.route('/delete/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):

        try:
            question = Question.query.filter(
                Question.id == question_id).one_or_none()

            if question is None:
                abort(404)

            question.delete()
            selection = Question.query.order_by(Question.id).all()
            current_questions = paginate_questions(request, selection)

            return jsonify({
                'success': True,
                'deleted': question_id,
                #'questions': current_questions,
                #'total_questions': len(current_questions)
            })

        except ():
            abort(422)

    ''' 
  Create an endpoint to POST a new question, 
  which will require the question and answer text, 
  category, and difficulty score.

  TEST: When you submit a question on the "Add" tab, 
  the form will clear and the question will appear at the end of the last page
  of the questions list in the "List" tab.  
  '''

    @app.route('/questions', methods=['POST'])
    def add_question():
        body = request.get_json()

        new_question = body.get('question', None)
        new_answer = body.get('answer', None)
        new_difficulty = body.get('difficulty', None)
        new_category = body.get('category', None)

        try:
            question = Question(question=new_question,
                                answer=new_answer,
                                difficulty=new_difficulty,
                                category=new_category)
            question.insert()

            selection = Question.query.order_by(Question.id).all()
            current_questions = paginate_questions(request, selection)

            return jsonify({
                'success': True,
                'added': question.id,
                'questions': current_questions,
                'total_questions': len(Question.query.all())
            })

        except ():
            print(sys.exc_info())
            abort(422)

    '''
  
  Create a POST endpoint to get questions based on a search term. 
  It should return any questions for whom the search term 
  is a substring of the question. 

  TEST: Search by any phrase. The questions list will update to include 
  only question that include that string within their question. 
  Try using the word "title" to start. 
  '''

    @app.route('/questions/search', methods=['POST'])
    def search_question():
        body = request.get_json()
        search_term = body.get('searchTerm', None)
        search = '%{}%'.format(search_term)
        search_result = Question.query.filter(
            Question.question.ilike(search)).all()

        if (search_result is None):
            abort(404)

        formatted_questions = [result.format() for result in search_result]

        return jsonify({
            'success': True,
            'questions': formatted_questions,
            'total_questions': len(formatted_questions)
        })

    '''
  Create a GET endpoint to get questions based on category. 

  TEST: In the "List" tab / main screen, clicking on one of the 
  categories in the left column will cause only questions of that 
  category to be shown. 
  '''

    @app.route('/categories/<int:category_id>/questions/', methods=['GET'])
    def get_questions_by_categories(category_id):

        selection = Question.query.filter(
            Question.category == category_id).all()

        current_questions = paginate_questions(request, selection)

        if len(current_questions) == 0:
            abort(404)

        return jsonify({
            'success': True,
            'current_category': category_id,
            'questions': current_questions,
        })

    '''
  Create a POST endpoint to get questions to play the quiz. 
  This endpoint should take category and previous question parameters 
  and return a random questions within the given category, 
  if provided, and that is not one of the previous questions. 

  TEST: In the "Play" tab, after a user selects "All" or a category,
  one question at a time is displayed, the user is allowed to answer
  and shown whether they were correct or not. 
  '''

    @app.route('/quiz', methods=['POST'])
    def get_random_quiz_questions():

        try:
            body = request.get_json()

            quiz_category = body.get('quiz_category')
            previous_questions = body.get('previous_questions')

            if ((quiz_category is None) or (previous_questions is None)):
                abort(400)

            category_id = quiz_category['id']

            if (category_id == 0):
                questions = Question.query.filter(
                    Question.id.notin_(previous_questions)).all()

            else:
                questions = Question.query.filter(
                    Question.category == category_id).filter(
                        Question.id.notin_(previous_questions)).all()

            if len(questions) > 0:
                next_question = random.choice(questions).format()

                return jsonify({'success': True, 'question': next_question})

            else:
                return jsonify({'question': None})

        except:
            abort(422)

    '''
  Create error handlers for all expected errors 
  including 404 and 422. 
  '''

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            'success': False,
            'error': 404,
            'message': 'Resource not found'
        }), 404

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            'success': False,
            'error': 400,
            'message': 'Bad Request'
        }), 400

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            'success': False,
            'error': 422,
            'message': 'Unprocessable entity'
        }), 422

    @app.errorhandler(500)
    def server_error(error):
        return jsonify({
            'success': False,
            'error': 500,
            'message': 'Internal server error'
        }), 500

    return app
Example #6
0
def create_app():
    """
    @TODO: Set up CORS. Allow '*' for origins. Delete the sample route after completing the TODOs
    """
    app = Flask(__name__)
    setup_db(app)

    CORS(app, resources={r'/*': {'origins': '*'}})

    @app.after_request
    def set_headers(response):
        """
        @TODO: Use the after_request decorator to set Access-Control-Allow
        """
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type, Authorization, true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET, PATCH, POST, DELETE, OPTIONS')
        return response

    @app.route('/categories', methods=['GET'])
    def get_all_categories():
        """
          Create an endpoint to handle GET requests 
          for all available categories.
        """
        categories = {}
        for category in Category.query.all():
            categories[category.id] = category.type
        return jsonify({'categories': categories})
#  Get Questions - working
#  ----------------------------------------------------------------

    @app.route('/questions', methods=['GET'])
    def get_questions():
        categories = {}
        for category in Category.query.all():
            categories[category.id] = category.type
        questions = [question.format() for question in Question.query.all()]
        page = int(request.args.get('page', '0'))
        upper_limit = page * 10
        lower_limit = upper_limit - 10
        return jsonify({
            'questions':
            questions[lower_limit:upper_limit] if page else questions,
            'total_questions':
            len(questions),
            'categories':
            categories
        })
#  Delete Questions - working
#  ----------------------------------------------------------------

    @app.route('/questions/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):
        question = Question.query.get(question_id)
        if not question:
            return abort(404, f'No question found with id: {question_id}')
        question.delete()
        return jsonify({'deleted': question_id})
#  Submit Question - working
#  ----------------------------------------------------------------

    @app.route('/questions', methods=['POST'])
    def post_question():
        question = request.json.get('question')
        answer = request.json.get('answer')
        category = request.json.get('category')
        difficulty = request.json.get('difficulty')
        if not (question and answer and category and difficulty):
            return abort(
                400, 'Required question object keys missing from request '
                'body')
        question_entry = Question(question, answer, category, difficulty)
        question_entry.insert()
        return jsonify({'question': question_entry.format()})
#  Search Questions - not working
#  ----------------------------------------------------------------

    @app.route("/search", methods=['POST'])
    def search_questions():
        if request.data:
            page = 1
            if request.args.get('page'):
                page = int(request.args.get('page'))
            search_data = json.loads(request.data.decode('utf-8'))
            if 'searchTerm' in search_data:
                questions_query = Question.query.filter(
                    Question.question.like('%' + search_data['searchTerm'] +
                                           '%')).paginate(
                                               page, QUESTIONS_PER_PAGE, False)
                questions = list(map(Question.format, questions_query.items))
                if len(questions) > 0:
                    result = {
                        "success": True,
                        "questions": questions,
                        "total_questions": questions_query.total,
                        "current_category": None,
                    }
                    return jsonify(result)
            abort(404)
        abort(422)
#  Filter questions via category - working
#  ----------------------------------------------------------------

    @app.route('/categories/<int:category_id>/questions', methods=['GET'])
    def get_questions_by_category(category_id):
        if not category_id:
            return abort(400)
        questions = [
            question.format() for question in Question.query.filter(
                Question.category == category_id)
        ]
        return jsonify({
            'questions': questions,
            'total_questions': len(questions),
            'current_category': category_id
        })
#  Play game - render questions with optional category - working
#  ----------------------------------------------------------------

    @app.route("/quizzes", methods=['POST'])
    def get_question_for_quiz():
        body = request.get_json()
        previous_questions = body.get('previous_questions', [])
        quiz_category = body.get('quiz_category', None)

        try:
            if quiz_category:
                if quiz_category['id'] == 0:
                    selections = Question.query.all()
                else:
                    selections = Question.query.filter_by(
                        category=quiz_category['id']).all()

            options = [
                question.format() for question in selections
                if question.id not in previous_questions
            ]
            if len(options) == 0:
                return jsonify({'question': False})
            result = random.choice(options)
            return jsonify({'question': result})
        except:
            abort(500)

# Error Handlers
#  ----------------------------------------------------------------

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "Unprocessable"
        }), 422

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "Resource not found"
        }), 404

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "Bad Request"
        }), 400

    @app.errorhandler(500)
    def server_error(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "Server error"
        }), 500

    return app
Example #7
0
def create_app(test_config=None):
    app = Flask(__name__)
    setup_db(app)
    CORS(app)

    oauth = OAuth(app)

    secret = secrets.token_urlsafe(32)
    app.secret_key = secret
    auth0 = oauth.register(
        'auth0',
        client_id=os.environ.get('CLIENT_ID'),
        client_secret=os.environ.get('CLIENT_SECRET'),
        api_base_url=os.environ.get('API_BASE_URL'),
        access_token_url=os.environ.get('ACCESS_TOKEN_URL'),
        authorize_url=os.environ.get('AUTHORIZE_URL'),
        client_kwargs={
            'scope': 'openid profile email',
        },
    )
    AUTH0_URL = os.environ.get('AUTH0_LOGIN_URL')

    CORS(app, resources={r"/api/*": {"origins": "*"}})

    # ROUTES

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PUT,POST,DELETE,OPTIONS')
        return response

    # main page

    @app.route('/')
    def index():
        return 'Hello, friend !'

    # login page
    @app.route('/login')
    def login():
        return render_template('login.html', AUTH0_AUTHORIZE_URL=AUTH0_URL)

    # logout

    @app.route('/logout')
    def logout():
        # Clear session stored data
        session.clear()
        # Redirect user to logout endpoint
        params = {'returnTo': url_for(
            'index', _external=True), 'client_id': '5FmE550Gvrv7iLRl1WxYleKWZx44su3a'}
        return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))

    # GET endpoints
    ##################################################################

    # retrieves all the actors

    @app.route('/actors', methods=['GET'])
    @requires_auth('get:actors')
    def show_actors(jwt):
        actors = Actor.query.all()
        if actors is None:
            abort(404)

        actors_list = []
        for actor in actors:
            actors_list.append({
                'actor_id': actor.id,
                'actor_name': actor.name,
                'actor_age': actor.age,
                'actor_gender': actor.gender
            })

        return jsonify({
            'success': True,
            'actors': actors_list
        })

    # retrieves all the movies

    @app.route('/movies', methods=['GET'])
    @requires_auth('get:movies')
    def show_movies(jwt):
        movies = Movie.query.all()
        if movies is None:
            abort(404)

        movies_list = []
        for movie in movies:
            movies_list.append({
                'movie_id': movie.id,
                'movie_title': movie.title,
                'movie_release_date': movie.release_date
            })

        return jsonify({
            'success': True,
            'movies': movies_list
        })

    # retrieves a certain actor
    @app.route('/actors/<int:actor_id>', methods=['GET'])
    @requires_auth('get:actor')
    def show_actor(jwt, actor_id):
        actor = Actor.query.filter(Actor.id == actor_id).one_or_none()
        if actor is None:
            abort(404)

        return jsonify({
            'success': True,
            'name': actor.name,
            'age': actor.age,
            'gender': actor.gender
        })

    # retrieves a certain movie

    @app.route('/movies/<int:movie_id>', methods=['GET'])
    @requires_auth('get:movie')
    def show_movie(jwt, movie_id):
        movie = Movie.query.filter(Movie.id == movie_id).one_or_none()
        if movie is None:
            abort(404)

        return jsonify({
            'success': True,
            'title': movie.title,
            'release_date': movie.release_date
        })

    # Delete endpoints
    ##################################################################

    # deletes a certain actor

    @app.route('/actors/<int:actor_id>', methods=['DELETE'])
    @requires_auth('delete:actor')
    def delete_actor(jwt, actor_id):
        try:
            actor = Actor.query.filter(Actor.id == actor_id).one_or_none()

            if actor is None:
                abort(404)

            actor.delete()

            return jsonify({
                "success": True,
                "deleted": actor_id
            })
        except Exception:
            abort(422)

    # retrieves a certain movie

    @app.route('/movies/<int:movie_id>', methods=['DELETE'])
    @requires_auth('delete:movie')
    def delete_movie(jwt, movie_id):
        try:
            movie = Movie.query.filter(Movie.id == movie_id).one_or_none()

            if movie is None:
                abort(404)

            movie.delete()

            return jsonify({
                "success": True,
                "deleted": movie_id
            })
        except Exception:
            abort(422)

    # POST endpoints
    ##################################################################

    # adds a new actor

    @app.route('/actors', methods=['POST'])
    @requires_auth('post:actor')
    def add_actor(jwt):
        body = request.get_json()
        if body is None:
            abort(400)

        new_name = body.get('name', None)
        new_age = body.get('age', None)
        new_gender = body.get('gender', None)
        try:
            if new_name and new_age and new_gender:
                new_actor = Actor(
                    name=new_name,
                    age=new_age,
                    gender=new_gender
                )
                new_actor.insert()
                return jsonify({
                    'success': True,
                    'created_id': new_actor.id,
                    'actors': [actor.format() for actor in Actor.query.all()]
                })

            else:
                abort(422)
        except Exception:
            abort(422)

    # adds a new movie

    @app.route('/movies', methods=['POST'])
    @requires_auth('post:movie')
    def add_movie(jwt):
        body = request.get_json()
        if body is None:
            abort(400)

        new_title = body.get('title', None)
        release_date_str = body.get('release_date', None)
        y, m, d = release_date_str.split('-')
        new_release_date = datetime(int(y), int(m), int(d)).date()
        try:
            if new_title and release_date_str:
                new_movie = Movie(
                    title=new_title, release_date=new_release_date)

                new_movie.insert()
                return jsonify({
                    'success': True,
                    'created_id': new_movie.id,
                    'movies': [movie.format() for movie in Movie.query.all()]
                })

            else:
                abort(422)
        except Exception:
            abort(422)

    # PATCH endpoints
    ##################################################################
    # updates an existing actor

    @app.route('/actors/<int:actor_id>', methods=['PATCH'])
    @requires_auth('patch:actor')
    def update_actor(jwt, actor_id):

        actor = Actor.query.filter(Actor.id == actor_id).one_or_none()
        if actor is None:
            abort(404)

        body = request.get_json()
        if body is None:
            abort(400)

        new_name = body.get('name', None)
        new_age = body.get('age', None)
        new_gender = body.get('gender', None)
        try:
            if new_name:
                actor.name = new_name

            if new_age:
                actor.age = new_age

            if new_gender:
                actor.gender = new_gender

            actor.update()

            return jsonify({
                "success": True,
                "actor": [actor.format() for actor in Actor.query.all()]
            })
        except Exception:
            abort(422)

    # updates an existing movie

    @app.route('/movies/<int:movie_id>', methods=['PATCH'])
    @requires_auth('patch:movie')
    def update_movie(jwt, movie_id):

        movie = Movie.query.filter(Movie.id == movie_id).one_or_none()
        if movie is None:
            abort(404)

        body = request.get_json()
        if body is None:
            abort(400)

        new_title = body.get('title', None)
        new_release_date_str = body.get('release_date', None)

        try:
            if new_title:
                movie.title = new_title

            if new_release_date_str:
                y, m, d = new_release_date_str.split('-')
                new_release_date = datetime(int(y), int(m), int(d)).date()
                movie.release_date = new_release_date

            movie.update()

            return jsonify({
                "success": True,
                "movies": [movie.format() for movie in Movie.query.all()]
            })
        except Exception:
            abort(422)

    # Error Handling

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(AuthError)
    def authentication_error(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": "AuthError"
        }), 401

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": 'bad request'
        }), 400

    return app
def initialize_app():
    app = Flask(__name__)
    setup_db(app)
    CORS(app)
    return app
Example #9
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    app.config.from_object('config')
    CORS(app)

    setup_db(app)
    db = SQLAlchemy(app)
    Migrate(app, db)

    @app.route('/')
    def index():
        return ("hello word")

    @app.route('/actors', methods=["GET"])
    @requires_auth('get:actors')
    def get_actors(payload):
        actors = Actor.query.all()
        return jsonify({
            "actors": [actor.format() for actor in actors],
            "success": True
        })

    @app.route('/actors', methods=["POST"])
    @requires_auth('post:actors')
    def create_actor(payload):
        body = request.get_json()
        name = body.get("name")
        age = body.get("age")
        gender = body.get("gender")

        if not name or not age or not gender:
            abort(400)

        actor = Actor(name=name, age=age, gender=gender)
        actor.insert()
        return jsonify({"actor": actor.format(), "success": True})

    @app.route('/actors/<actor_id>', methods=["PATCH"])
    @requires_auth('patch:actors')
    def update_actor(payload, actor_id):
        body = request.get_json()
        name = body.get("name", None)
        age = body.get("age", None)
        gender = body.get("gender", None)
        actor = Actor.query.filter_by(id=actor_id).first_or_404()
        if name:
            actor.name = name
        if age:
            actor.age = age
        if gender:
            actor.gender = gender

        actor.update()
        return jsonify({"actor": actor.format(), "success": True})

    @app.route('/actors/<actor_id>', methods=["DELETE"])
    @requires_auth('delete:actors')
    def delete_actor(payload, actor_id):
        actor = Actor.query.filter_by(id=actor_id).first_or_404()
        actor.delete()
        return jsonify({"success": True})

    @app.route('/movies', methods=["GET"])
    @requires_auth('get:movies')
    def get_movies(payload):
        movies = Movie.query.all()
        return jsonify({
            "movies": [movie.format() for movie in movies],
            "success": True
        })

    @app.route('/movies', methods=["POST"])
    @requires_auth('post:movies')
    def create_movie(payload):
        body = request.get_json()
        title = body.get("title")
        release_date = body.get("release_date")

        if not title or not release_date:
            abort(400)
        movie = Movie(title=title, release_date=release_date)
        movie.insert()
        return jsonify({"movie": movie.format(), "success": True})

    @app.route('/movies/<movie_id>', methods=["PATCH"])
    @requires_auth('patch:movies')
    def update_movie(payload, movie_id):
        body = request.get_json()
        movie = Movie.query.filter_by(id=movie_id).first_or_404()
        movie.title = body.get("title")
        movie.release_date = body.get("release_date")

        movie.update()
        return jsonify({"movie": movie.format(), "success": True})

    @app.route('/movies/<movie_id>', methods=["DELETE"])
    @requires_auth('delete:movies')
    def delete_movie(payload, movie_id):
        movie = Movie.query.filter_by(id=movie_id).first_or_404()
        movie.delete()
        return jsonify({"success": True})

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            'success': False,
            'error': 404,
            'message': "Not found"
        }), 404

    @app.errorhandler(422)
    def unprocessible(error):
        return jsonify({
            'success': False,
            'error': 422,
            'message': "Unprocessible"
        }), 422

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            'success': False,
            'error': 400,
            'message': "Bad Request"
        }), 400

    @app.errorhandler(405)
    def bad_request(error):
        return jsonify({
            'success': False,
            'error': 405,
            'message': "Method not found"
        }), 405

    @app.errorhandler(401)
    def unauthenticated(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": "unauthenticated"
        }), 401

    @app.errorhandler(AuthError)
    def auth_error(ex):
        return jsonify({
            "success": False,
            "error": ex.status_code,
            "message": ex.error['description']
        }), ex.status_code

    return app
Example #10
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)
    '''
  @TODO: Set up CORS. Allow '*' for origins. Delete the sample route after completing the TODOs
  '''
    CORS(app)
    '''
  @TODO: Use the after_request decorator to set Access-Control-Allow
  '''
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type, Authorization')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET, POST, DELETE')
        return response

    '''
  @TODO: 
  Create an endpoint to handle GET requests 
  for all available categories.
  '''

    @app.route('/categories')
    def get_categories():
        categories = Category.query.order_by(Category.id).all()
        if not len(categories):
            abort(404)

        formatted_categories = {
            category.id: category.type
            for category in categories
        }
        return jsonify({'success': True, 'categories': formatted_categories})

    '''
  @TODO: 
  Create an endpoint to handle GET requests for questions, 
  including pagination (every 10 questions). 
  This endpoint should return a list of questions, 
  number of total questions, current category, categories. 

  TEST: At this point, when you start the application
  you should see questions and categories generated,
  ten questions per page and pagination at the bottom of the screen for three pages.
  Clicking on the page numbers should update the questions. 
  '''

    @app.route('/questions')
    def get_questions():
        page = request.args.get('page', 1, type=int)
        start = (page - 1) * QUESTIONS_PER_PAGE
        end = start + QUESTIONS_PER_PAGE
        questions = Question.query.all()
        formatted_questions = [question.format() for question in questions]

        if not len(formatted_questions[start:end]):
            abort(404)

        categories = Category.query.order_by(Category.type).all()
        formatted_categories = {
            category.id: category.type
            for category in categories
        }
        return jsonify({
            'success': True,
            'questions': formatted_questions[start:end],
            'total_questions': len(formatted_questions),
            'categories': formatted_categories
        })

    '''
  @TODO: 
  Create an endpoint to DELETE question using a question ID. 

  TEST: When you click the trash icon next to a question, the question will be removed.
  This removal will persist in the database and when you refresh the page. 
  '''

    @app.route('/questions/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):
        question = Question.query.filter_by(id=question_id).one_or_none()
        if question is None:
            abort(404)
        else:
            question.delete()
            return jsonify({'success': True, 'question_id': question_id})

    '''
  @TODO: 
  Create an endpoint to POST a new question, 
  which will require the question and answer text, 
  category, and difficulty score.

  TEST: When you submit a question on the "Add" tab, 
  the form will clear and the question will appear at the end of the last page
  of the questions list in the "List" tab.  
  '''

    @app.route('/questions', methods=['POST'])
    def add_question():
        body = request.get_json()
        if body.get('searchTerm'):
            return search_question()
        try:
            q = Question(body['question'], body['answer'], body['category'],
                         body['difficulty'])
            q.insert()
            return jsonify({'success': True, 'id': q.id})

        except:
            abort(422)

    '''
  @TODO: 
  Create a POST endpoint to get questions based on a search term. 
  It should return any questions for whom the search term 
  is a substring of the question. 

  TEST: Search by any phrase. The questions list will update to include 
  only question that include that string within their question. 
  Try using the word "title" to start. 
  '''

    @app.route('/questions', methods=['POST'])
    def search_question():
        body = request.get_json()
        searchTerm = body['searchTerm'].lower()
        try:
            questions = Question.query.filter(
                Question.question.ilike("%{}%".format(searchTerm))).all()
            questions = [q.format() for q in questions]
            return jsonify({
                'success': True,
                'questions': questions,
                'total_questions': len(questions)
            })
        except:
            abort(422)

    '''
  @TODO: 
  Create a GET endpoint to get questions based on category. 

  TEST: In the "List" tab / main screen, clicking on one of the 
  categories in the left column will cause only questions of that 
  category to be shown. 
  '''

    @app.route('/categories/<int:category_id>/questions')
    def get_questions_by_category_id(category_id):
        category_questions = Question.query.filter_by(
            category=category_id).all()
        if not category_questions:
            abort(404)
        else:
            category_questions = [q.format() for q in category_questions]
        return jsonify({
            'success': True,
            'questions': category_questions,
            'total_questions': len(category_questions)
        })

    '''
  @TODO: 
  Create a POST endpoint to get questions to play the quiz. 
  This endpoint should take category and previous question parameters 
  and return a random questions within the given category, 
  if provided, and that is not one of the previous questions. 

  TEST: In the "Play" tab, after a user selects "All" or a category,
  one question at a time is displayed, the user is allowed to answer
  and shown whether they were correct or not. 
  '''

    @app.route('/quizzes', methods=['POST'])
    def play_quiz():
        category_id = request.get_json()['quiz_category']['id']
        previous_questions = request.get_json()['previous_questions']
        if category_id == 0:
            questions_to_ask = Question.query.filter(
                ~Question.id.in_(previous_questions)).all()
        else:
            questions_to_ask = Question.query.filter_by(category=category_id). \
              filter(~Question.id.in_(previous_questions)).all()

        if not questions_to_ask:
            return jsonify({
                'previousQuestions': previous_questions,
                'question': None
            })

        currentQuestion = random.choice(questions_to_ask).format()
        return jsonify({
            'previousQuestions': currentQuestion['id'],
            'question': currentQuestion
        })

    '''
  @TODO: 
  Create error handlers for all expected errors 
  including 404 and 422. 
  '''

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "Bad request"
        }), 400

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "Not found"
        }), 404

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(500)
    def internal_server_error(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "It's not you, it's us"
        }), 500

    return app
Example #11
0
def create_app(test_config=None):
  # create and configure the app
  app = Flask(__name__)
  setup_db(app)

  CORS(app, resources={r"/*": {"origins": '*'}})

  @app.after_request
  def after_request(response):
    response.headers.add('Access-Control-Allow-Headers', 'Content-Type, Authorization')
    response.headers.add('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS')
    return response

  @app.route('/categories', methods=['GET'])
  def get_categories():
    categories_query = Category.query.all()
    categories = {}
    for category in categories_query:
      categories[category.id] = category.type
    if categories_query is None:
      abort(404)
    else:
      return jsonify({
        'success': True,
        'categories': categories
      })

  @app.route('/questions', methods=['GET'])
  def get_paginated_questions():
    # get all questions
    query_questions = Question.query.all()
    page = request.args.get('page', 1, type=int)
    begin_index = (page - 1) * QUESTIONS_PER_PAGE
    end_index = begin_index + QUESTIONS_PER_PAGE
    questions = [question.format() for question in query_questions]
    totalQuestions = len(questions)

    # get all categories (from Category model)
    categories_query = Category.query.all()
    categories = {}
    for category in categories_query:
      categories[category.id] = category.type

    currentCategory = None # I had a problem to understand where should I take it from, and what is it used for, I took the solution from https://knowledge.udacity.com/questions/82424
    if query_questions is None or categories_query is None:
      abort(404)
    else:
      return jsonify({
        'success': True,
        'questions': questions[begin_index:end_index],
        'totalQuestions': totalQuestions,
        'currentCategory': currentCategory,
        'categories': categories
      })

  @app.route('/questions/<int:question_id>', methods=['DELETE'])
  def delete_question(question_id):
    try:
      question_to_be_deleted = Question.query.get(question_id)
      question_to_be_deleted.delete()
    except:
      db.session.rollback()
      if question_to_be_deleted is None:
        abort(404)
      else:
        abort(422)
    finally:
      db.session.close()
    return jsonify({
      'success': True,
      'deleted': question_id
       })

  @app.route('/questions', methods=['POST'])
  def create_question():
    try:
      if request.method == 'PUT':
        abort(405)
      else:
        body = request.get_json()
        question = body.get('question')
        answer = body.get('answer')
        category = body.get('category')
        difficulty = body.get('difficulty')
        question_to_be_created = Question(question=question, answer=answer, category=category, difficulty=difficulty)
        question_to_be_created.insert()
    except:
      db.session.rollback()
      abort(422)
    finally:
      db.session.close()
    return jsonify({
      'success': True
    })

  @app.route('/questions/search', methods=['POST'])
  def get_question_based_on_search():
    body = request.get_json()
    search_term = body.get('searchTerm', '')
    search_result = Question.query.filter(Question.question.ilike(f'%{search_term}%')).all()
    questions = [question.format() for question in search_result]
    if search_term is None:
      abort(404)
    else:
      return jsonify({
        'success': True,
        'questions': questions
      })

  @app.route('/categories/<int:category_id>/questions', methods=['GET'])
  def get_question_for_category(category_id):
    requested_category = Category.query.get(category_id)
    questions_query = Question.query.filter(Question.category == requested_category).all()
    questions = [question.format() for question in questions_query]
    if requested_category is None:
      abort(404)
    else:
      return jsonify({
        'success': True,
        'questions': questions,
        'totalQuestions': len(questions),
        'currentCategory': requested_category.type
      })

  @app.route('/quizzes', methods=['POST'])
  def get_questions():
    try:
      body = request.get_json()
      category = body.get('quiz_category')
      previous_question = body.get('previous_questions')
      query_questions = Question.query.filter(Question.category == category).filter(Question.id not in previous_question).all()
      if query_questions is None:
        abort(404)
      else:
        questions = [question.format() for question in query_questions]
        random_index = random.randint(1, len(questions))
    except:
      abort(422)
    return jsonify({
      'success': True,
      'questions': questions[random_index]
    })

  @app.errorhandler(404)
  def not_found(error):
    return jsonify({
      'success': False,
      'error': 404,
      'message': 'resource not found'
    }), 404

  @app.errorhandler(405)
  def method_not_allowed(error):
    return jsonify({
      'success': False,
      'error': 405,
      'message': 'method not allowed'
    }), 405

  @app.errorhandler(422)
  def unprocessable_request(error):
    return jsonify({
      'success': False,
      'error': 422,
      'message': 'unprocessable'
    }), 422
  
  return app

    
Example #12
0
def create_app(test_config=None):
    # configure app
    app = Flask(__name__)
    CORS(app)
    setup_db(app)
    Migrate(app, db)

    @app.route('/')
    def index():
        return "API tests for Casting Agency project"

    @app.after_request
    def after_request(response):
        header = response.headers
        header['Access-Control-Allow-Origin'] = '*'
        return response

    @app.route('/actors', methods=['GET'])
    @requires_auth(permission='get:actors')
    def actors():
        """
            Returns a list of actors
        """
        try:
            actors_list = [
                actor.actor_information_format()
                for actor in Actor.query.order_by(Actor.id).all()
            ]

            return jsonify({'success': True, 'actors': actors_list})
        except Exception as e:
            print(e)
            abort(422)

    @app.route('/actors', methods=['POST'])
    @requires_auth(permission='post:actors')
    def post_actors():
        """
        Posts actors and movie played by the actors
        """
        name = request.get_json()['name']
        age = request.get_json()['age']
        gender = request.get_json()['gender']
        actor = Actor(name=name, age=age, gender=gender)
        actor.insert()

        return jsonify({
            "success": True,
            "status_code": 200,
            "actor": actor.actor_information_format()
        })

    @app.route('/assign_movie_to_actor/', methods=['POST'])
    @requires_auth(permission='post:actors')
    def post_actors_movie():
        """
        post actors with assigned movies or movies with assigned_actors
        """
        try:
            assigned_movie = helper_table.insert().values(
                actor_id=request.get_json()['actor_id'],
                movie_id=request.get_json()['movie_id'])

            db.session.execute(assigned_movie)
            db.session.commit()
            return jsonify({
                "success": True,
                "status_code": 200,
                "message": 'OK'
            })
        except:
            abort(404)

    @app.route('/actors/<int:actor_id>', methods=['PATCH'])
    @requires_auth(permission='patch:actors')
    def update_actors(actor_id):
        """
        Updates actors data
        """
        name = request.get_json()['name']
        age = request.get_json()['age']
        gender = request.get_json()['gender']
        played_in_movies = request.json.get("movies", None)
        actor = Actor.query.filter(Actor.id == actor_id).one_or_none()

        if actor is None:
            abort(404)

        if played_in_movies:
            actor.movies = []
            actor.update()

            for movie in played_in_movies:
                actor.movies.append(Movie.query.get(movie))

        if name:
            actor.name = name
        if age:
            actor.age = age
        if gender:
            actor.gender = gender
        actor.update()

        return jsonify({
            "success": True,
            "status_code": 200,
            "actor": actor.actor_information_format()
        })

    @app.route('/actors/<int:actor_id>', methods=['DELETE'])
    @requires_auth(permission='delete:actors')
    def delete_actors(actor_id):
        """
        deletes actors data
        """
        actor = Actor.query.filter(Actor.id == actor_id).one_or_none()
        if actor is None:
            abort(404)
        actor.delete()

        return jsonify({
            "success": True,
            "status_code": 200,
            "status_message": 'OK',
            "id_deleted": actor_id
        })

    # Movie Routes

    @app.route('/movies', methods=["GET"])
    @requires_auth(permission='get:movies')
    def movies():
        """
        Returns a list of movies
        """
        try:
            movies_list = [
                movie.movie_information_format()
                for movie in Movie.query.order_by(Movie.id).all()
            ]
            return jsonify({
                "success": True,
                "status_code": 200,
                "status_message": 'OK',
                "movies": movies_list
            })
        except Exception:
            abort(422)

    @app.route('/movies', methods=['POST'])
    @requires_auth(permission='post:movies')
    def post_movies():
        """
        Posts movies and actors that play in the movies
        """
        title = request.get_json()['title']
        release_date = request.get_json()['release_date']
        if title is None:
            abort(422)
        movie = Movie(title=title, release_date=release_date)
        movie.insert()
        return jsonify({
            "success": True,
            "status_code": 200,
            "status_message": 'OK',
            "movie": movie.movie_information_format()
        })

    @app.route('/movies/<int:movie_id>', methods=['GET', 'PATCH'])
    @requires_auth(permission='patch:movies')
    def update_movies(movie_id):
        """
        Updates movies data
        """
        title = request.get_json()['title']
        release_date = request.get_json()['release_date']
        cast = request.get_json()['cast']
        movie = Movie.query.filter(Movie.id == movie_id).one_or_none()

        if movie is None:
            abort(404)

        if cast:
            movie.actors = []
            movie.update()
            for person in cast:
                movie.actors.append(Actor.query.get(person))

        if title:
            movie.title = title
        if release_date:
            movie.release_date = release_date
        movie.update()

        return jsonify({
            "success": True,
            "status_code": 200,
            "status_message": 'OK',
            "movie": movie.movie_information_format()
        })

    @app.route('/movies/<int:movie_id>', methods=['DELETE'])
    @requires_auth(permission='delete:movies')
    def delete_movies(movie_id):
        """
        deletes movies data
        """
        movie = Movie.query.filter(Movie.id == movie_id).one_or_none()

        if movie is None:
            abort(404)
        movie.delete()

        return jsonify({
            "success": True,
            "status_code": 200,
            "status_message": 'OK',
            "id_deleted": movie_id
        })

    # Error Handeling

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "status_message": "unprocessable"
        }), 422

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "status_message": "resource Not found"
        }), 404

    @app.errorhandler(AuthError)
    def auth_error(error):
        return jsonify(error.error), error.status_code

    return app
Example #13
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)

    '''
    @TODO: Set up CORS. Allow '*' for origins.
    Delete the sample route after completing the TODOs.
    '''
    CORS(app)

    '''
    @TODO: Use the after_request decorator to set Access-Control-Allow
    '''
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Origin', '*')
        response.headers.add('Access-Control-Allow-Hearders',
                             'Content-Type,Autorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PATCH,POST,DELETE,OPTIONS')
        return response

    '''
    @TODO:
    Create an endpoint to handle GET requests
    for all available categories.
    '''
    @app.route('/categories')
    def get_categories():

        try:
            categories = Category.query.order_by(Category.id).all()
        except Exception as e:
            print(e)
            abort(422)

        list_categories = [category.format() for category in categories]

        dict_categories = {}
        if len(list_categories) == 0:
            abort(404)
        else:
            for cat in list_categories:
                dict_categories[cat["id"]] = cat["type"]

        return jsonify({
            'success': True,
            'categories': dict_categories,
            'number_categories': len(list_categories)
        })

    '''
    @TODO:
    Create an endpoint to handle GET requests for questions,
    including pagination (every 10 questions).
    This endpoint should return a list of questions,
    number of total questions, current category, categories.

    TEST: At this point, when you start the application
    you should see questions and categories generated,
    ten questions per page and pagination at the bottom
    of the screen for three pages.
    Clicking on the page numbers should update the questions.
    '''

    def paginate_questions(request, selection):
        page = request.args.get('page', 1, type=int)
        start = (page - 1) * QUESTIONS_PER_PAGE
        end = start + QUESTIONS_PER_PAGE

        list_questions = [question.format() for question in selection]
        current_list = list_questions[start:end]

        return current_list

    @app.route('/questions')
    def get_questions():

        try:
            questions = Question.query.order_by(Question.id).all()
            categories = Category.query.order_by(Category.id).all()
        except Exception as e:
            print(e)
            abort(422)

        current_list_questions = paginate_questions(request, questions)
        list_categories = [category.format() for category in categories]

        if len(current_list_questions) == 0:
            abort(404)

        dict_categories = {}
        for cat in list_categories:
            dict_categories[cat['id']] = cat['type']

        return jsonify({
            'success': True,
            'questions': current_list_questions,
            'page': request.args.get('page', 1, type=int),
            'total_questions': len(questions),
            'categories': dict_categories,
            'current_category': None
        })

    '''
    @TODO:
    Create an endpoint to DELETE question using a question ID.

    TEST: When you click the trash icon next to a question,
    the question will be removed.
    This removal will persist in the database and when you refresh the page.
    '''

    @app.route('/questions/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):

        try:
            question_to_delete = Question.query. \
                                 filter(Question.id == question_id). \
                                 one_or_none()
        except Exception as e:
            print(e)
            abort(422)

        if question_to_delete is None:
            abort(404)

        question_to_delete.delete()

        return jsonify({
            'success': True,
            'deleted': question_id,
            'total_number_questions': len(Question.query.all())
        })

    '''
    @TODO:
    Create an endpoint to POST a new question,
    which will require the question and answer text,
    category, and difficulty score.

    TEST: When you submit a question on the "Add" tab,
    the form will clear and the question will appear
    at the end of the last page
    of the questions list in the "List" tab.
    '''

    @app.route('/questions', methods=['POST'])
    def add_question():
        body = request.get_json()

        if body is None:
            abort(400)

        new_question = body.get('question', None)
        new_answer = body.get('answer', None)
        new_category = body.get('category', None)
        new_difficulty = body.get('difficulty', None)

        if all(v is not None for v in
               [new_question, new_answer, new_category, new_difficulty]):
            try:
                question_to_add = Question(question=new_question,
                                           answer=new_answer,
                                           category=new_category,
                                           difficulty=new_difficulty)
                question_to_add.insert()
                return jsonify({
                    'success': True,
                    'created': question_to_add.id,
                    'total_number_questions': len(Question.query.all())
                })
            except Exception as e:
                print(e)
                abort(422)
        else:
            abort(422)

    '''
    @TODO:
    Create a POST endpoint to get questions based on a search term.
    It should return any questions for whom the search term
    is a substring of the question.

    TEST: Search by any phrase. The questions list will update to include
    only question that include that string within their question.
    Try using the word "title" to start.
    '''

    @app.route('/questions/search', methods=['POST'])
    def search_questions():
        data = request.get_json()

        if data is None:
            abort(400)

        search_terms = data.get('searchTerm', None)

        if search_terms:
            try:
                list_questions = Question.query.order_by(Question.id). \
                                 filter(Question.question.
                                        ilike(f'%{search_terms}%'))
            except Exception as e:
                print(e)
                abort(422)

            formatted_list_questions = [question.format()
                                        for question in list_questions]

            if formatted_list_questions:
                return jsonify({
                    'success': True,
                    'search_terms': search_terms,
                    'questions': formatted_list_questions,
                    'total_questions': list_questions.count(),
                    'current_category': None
                })
            else:
                abort(404)
        else:
            abort(400)

    '''
    @TODO:
    Create a GET endpoint to get questions based on category.

    TEST: In the "List" tab / main screen, clicking on one of the
    categories in the left column will cause only questions of that
    category to be shown.
    '''

    @app.route('/categories/<int:category_id>/questions')
    def get_question_by_cat(category_id):

        # models.py is only what the python application can see and know.
        # foreign key is defined in trivia.psql
        try:
            list_questions = Question.query.order_by(Question.id). \
                             filter(Question.category == str(category_id)). \
                             all()
        except Exception as e:
            print(e)
            abort(422)

        if len(list_questions) == 0:
            abort(404)

        formatted_list_questions = [question.format()
                                    for question in list_questions]

        return jsonify({
            'questions': formatted_list_questions,
            'current_category': category_id,
            'success': True,
            'total_questions': len(formatted_list_questions)
        })

    '''
    @TODO:
    Create a POST endpoint to get questions to play the quiz.
    This endpoint should take category and previous question parameters
    and return a random questions within the given category,
    if provided, and that is not one of the previous questions.

    TEST: In the "Play" tab, after a user selects "All" or a category,
    one question at a time is displayed, the user is allowed to answer
    and shown whether they were correct or not.
    '''
    @app.route('/quizzes', methods=['POST'])
    def get_random_question():
        data = request.get_json()

        # if no json object is passed, the request is invalid.
        if data is None:
            abort(400)

        category = data.get('quiz_category', None)
        previous_questions = data.get('previous_questions', [])

        # if there are no value associated to 'quiz_category'
        if category is None:
            abort(400)

        try:
            if category['id'] != 0:
                list_questions = Question.query. \
                                 filter(Question.category == category['id']). \
                                 all()
            else:
                list_questions = Question.query.all()
        except Exception as e:
            print(e)
            abort(404)

        # In case the list of question is empty.
        if not list_questions:
            abort(404)

        # To randomize our list.
        # Not required since the order of results
        # returned change for every query.
        # But this adds a level of randomness.
        random.shuffle(list_questions)

        for q in list_questions:
            if q.id not in previous_questions:
                # the front end is taking care of
                # updating the previous_questions array.
                return jsonify({
                    'question': q.format(),
                    'quiz_category': q.category,
                    'success': True
                })

        # return None if all the questions of the category have been sent out.
        return jsonify({
            'question': None,
            'quiz_category': category['id'],
            'success': True
        })

    '''
    @TODO:
    Create error handlers for all expected errors
    including 404 and 422.
    '''

    @app.errorhandler(400)
    def invalide_request(error):
        return jsonify({
            'success': False,
            'error': 400,
            'message': 'invalid request'
        }), 400

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            'error': 404,
            'success': False,
            'message': 'resource not found'
        }), 404

    @app.errorhandler(422)
    def cant_process(error):
        return jsonify({
            'success': False,
            'error': 422,
            'message': 'unable to be processed'
        }), 422

    return app
Example #14
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)

    # CORS setup allowing '*' for origins.
    cors = CORS(app, resources={r"/api/*": {"origins": "*"}})

    # CORS Headers
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,POST,DELETE,OPTIONS')
        return response

    # endpoint to handle GET requests for all available categories.
    @app.route('/categories')
    def retrieve_categories():
        try:
            selection = Category.query.order_by(Category.id).all()
            categories = [category.format() for category in selection]

            if len(categories) == 0:
                abort(404)

            return jsonify({
                'success': True,
                'categories': categories,  # this returns categories as a list
                'categoriesasdict':
                get_category_list()  # this returns categories as a dictionary
            })
        except:
            abort(422)

    # Endpoint to handle GET requests for questions, including pagination
    @app.route('/questions')
    def retrieve_questions():

        try:
            selection = Question.query.order_by(Question.id).all()
            current_questions = paginate_questions(request, selection)

            if len(current_questions) == 0:
                abort(404)

            return jsonify({
                'success': True,
                'questions': current_questions,
                'total_questions': len(Question.query.all()),
                'categories': get_category_list(),
                'current_category': None
            })

        except:
            abort(422)

    # Endpoint to DELETE question using a question ID.
    @app.route('/questions/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):
        try:
            question = Question.query.filter(
                Question.id == question_id).one_or_none()

            if question is None:
                abort(404)

            question.delete()
            selection = Question.query.order_by(Question.id).all()
            current_questions = paginate_questions(request, selection)

            return jsonify({
                'success': True,
                'deleted': question_id,
                'questions': current_questions,
                'total_questions': len(Question.query.all()),
                'categories': get_category_list(),
                'current_category': None
            })

        except:
            abort(422)

    # Endpoint to create an endpoint to POST a new question, with the question and answer text, category, and difficulty score.
    @app.route('/questions', methods=['POST'])
    def create_question():
        body = request.get_json()

        new_question = body.get('question', None)
        new_answer = body.get('answer', None)
        new_difficulty = body.get('difficulty', None)
        new_category = body.get('category', None)

        try:
            question = Question(question=new_question,
                                answer=new_answer,
                                difficulty=new_difficulty,
                                category=new_category)
            question.insert()

            selection = Question.query.order_by(Question.id).all()
            current_questions = paginate_questions(request, selection)

            return jsonify({
                'success': True,
                'created': question.id,
                'questions': current_questions,
                'total_questions': len(Question.query.all()),
                'categories': get_category_list(),
                'current_category': None
            })

        except:
            abort(422)

    # Endpoint to search questions based on a search term
    @app.route('/questions/search', methods=['POST'])
    def search_questions():

        try:
            searchresults = request.get_json()
            searchterm = searchresults.get('searchTerm')
            selection = Question.query.filter(
                Question.question.ilike('%' + searchterm + '%')).all()

            current_questions = [question.format() for question in selection]

            # CURRENT ISSUE 1: If I am on page 1, and search results are 14, all 14 will be shown on page 1
            # and clicking on page 2 will show result of GET /questions?page=2

            # CURRENT ISSUE 2: if I am on page 2, and there is only 1 result, then it will show link to page 1
            # but will not navigate there directly.

            return jsonify({
                "questions": current_questions,
                "total_questions": len(selection),
                "current_category": None
            })

        except:
            abort(422)

    '''
  @TODO: 
  Create a GET endpoint to get questions based on category. 

  TEST: In the "List" tab / main screen, clicking on one of the 
  categories in the left column will cause only questions of that 
  category to be shown. 
  '''

    @app.route('/categories/<int:category_id>/questions')
    def get_questions_per_category(category_id):
        try:
            selection = Question.query.filter(
                Question.category == category_id).order_by(Question.id).all()
            current_questions = paginate_questions(request, selection)

            if len(current_questions) == 0:
                abort(404)

            # CURRENT ISSUE 1: If I am on page 1, and search results are 14, first 10 will be shown on page 1
            # and clicking on page 2 will show result of GET /questions?page=2

            # CURRENT ISSUE 2: if I am on page 2, and there is only 1 result, then it will show link to page 1
            # but will not navigate there directly.
            return jsonify({
                'questions':
                current_questions,
                'total_questions':
                len(current_questions),
                'current_category': (Category.query.filter(
                    Category.id == category_id).first()).type
            })

        except:
            abort(422)

    # POST endpoint to play the quiz.
    @app.route('/quizzes', methods=['POST'])
    def quiz_questions():
        try:
            body = request.get_json()
            current_category = body.get('quiz_category')
            previous_questions = body.get('previous_questions', None)

            # if 'ALL' is selected in the category selection criteria
            if current_category['id'] == 0:
                questions = Question.query.filter(
                    Question.id.notin_((previous_questions))).all()
            else:  # for a particular category
                questions = Question.query.filter(
                    Question.category == current_category['id']).filter(
                        Question.id.notin_((previous_questions))).all()

            if questions:
                current_question = random.choice(questions)
                return jsonify({
                    'success': True,
                    'question': current_question.format()
                })
            else:
                # once questions finish, this message will be shown
                return jsonify({
                    'success': True,
                    'question': {
                        'id': 1000,
                        'question': 'No more Questions :)',
                        'answer': 'No more Answers',
                        'category': 1,
                        'difficulty': 1
                    }
                })
        except:
            abort(422)

    # Error handlers for Errors in this code
    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    return app
Example #15
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)

    CORS(app)
    '''
    @TODO: Use the after_request decorator to set Access-Control-Allow
    '''
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PATCH,POST,DELETE,OPTIONS')
        return response

    @app.route('/categories')
    def get_categories():
        categories = [c.format() for c in Category.query.all()]
        return jsonify({'categories': categories})

    @app.route('/questions')
    def get_questions():
        page = request.args.get('page', 1, type=int)
        questions = [q.format() for q in Question.query.all()]
        start = (page - 1) * 10
        end = start + 10

        if len(questions) == 0:
            abort(404)

        categories = [c.format() for c in Category.query.all()]

        return jsonify({
            'questions': questions[start:end],
            'total_questions': len(questions),
            'categories': categories,
            'current_category': None
        })

    @app.route('/questions/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):
        question = Question.query.get(question_id)
        question.delete()
        return jsonify({'success': True})

    @app.route('/questions', methods=['POST'])
    def add_question():
        try:
            data = request.get_json()
            question = Question(data['question'], data['answer'],
                                data['category'], data['difficulty'])

            question.insert()

            return jsonify(question.format())
        except:
            abort(422)

    @app.route('/search', methods=['POST'])
    def search():
        page = request.args.get('page', 1, type=int)
        start = (page - 1) * 10
        end = start + 10
        data = request.get_json()
        questions = Question.query.filter(
            Question.question.ilike('%{}%'.format(data['searchTerm'])))
        formattedQuestions = [q.format() for q in questions]
        categories = [c.format() for c in Category.query.all()]

        return jsonify({
            'questions': formattedQuestions[start:end],
            'total_questions': len(formattedQuestions),
            'categories': categories
        })

    @app.route('/categories/<int:id>/questions')
    def get_categories_questions(id):
        page = request.args.get('page', 1, type=int)
        start = (page - 1) * 10
        end = start + 10
        questions = Question.query.filter_by(category=id + 1)
        formattedQuestions = [q.format() for q in questions]
        categories = [c.format() for c in Category.query.all()]
        return jsonify({
            'questions': formattedQuestions[start:end],
            'total_questions': len(formattedQuestions),
            'categories': categories,
            'current_category': None
        })

    @app.route('/quizzes', methods=['POST'])
    def quiz():
        data = request.get_json()
        category = data['quiz_category']['id']

        if category == 0:
            questions = Question.query.all()
        else:
            questions = Question.query.filter_by(category=category).all()

        questions = list(
            filter(lambda x: x not in data['previous_questions'], questions))

        if len(questions) == 0:
            abort(404)

        question = random.choice(questions)

        return jsonify({
            'question':
            question.format(),
            'previousQuestions':
            data['previous_questions'].append(question.id)
        })

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    return app
Example #16
0
File: app.py Project: cjgu/todo
            order=data['order'])

        todo = models.get_todo(todo_id)
        return todo, 200, {'Access-Control-Allow-Origin': '*'}


class TodoList(restful.Resource):

    def get(self):
        todos = models.get_todos()
        return sorted(todos, key=lambda t: t['order'])

    def post(self):
        data = json.loads(request.data)
        todo_schema.validate(data)

        todo = models.add_todo(
            text=data['text'],
            complete=data['complete'],
        )

        return todo, 201


api.add_resource(TodoList, '/todos')
api.add_resource(Todo, '/todos/<int:todo_id>')

if __name__ == '__main__':
    models.setup_db()
    app.run(debug = True)
Example #17
0
def create_app(test_config=None):
    app = Flask(__name__)
    setup_db(app)
    CORS(app)
    # CORS(app, resources={r"*/api/*": {origins: '*'}})

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type, Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET, POST, PATCH, DELETE, OPTIONS  ')
        return response

    #--# removed in FlaskII lesson #--#
    # @app.route('/')
    # # @cross_origin
    # def hello():
    #     return jsonify({'message': 'Hello?'})

    @app.route('/books', methods=['GET'])
    def get_books():
        books = Book.query.all()
        pagination = paginate_books(books)
        # zweite Seite aufrufbar mit: http://127.0.0.1:5000/books?page=2

        if len(pagination) == 0:
            abort(404)

        return jsonify({
            'success': True,
            'books': pagination,
            'total_books': len(books)
        })

    @app.route('/books/<int:book_id>')
    def get_specific_book(book_id):
        book = Book.query.filter(Book.id == book_id).one_or_none()

        if book is None:
            abort(404)
        else:
            return jsonify({
                'success': True,
                'book': book.format()
            })

    @app.route('/books/<int:book_id>', methods=['PATCH'])
    def update_book(book_id):

        body = request.get_json()

        try:
            book = Book.query.filter(Book.id == book_id).one_or_none()

            if book is None:
                abort(404)

            # nur rating kann geupdated werden
            if 'rating' in body:
                book.rating = int(body.get('rating'))

            book.update()

            return jsonify({
                'success': True,
                'id': book.id
            })

        except:
            abort(400)
        # for testing PATCH: curl http://127.0.0.1:5000/books/10 -X PATCH -H "Content-Type: application/json" -d '{"rating":"9"}'

    @app.route('/books/<int:book_id>', methods=['DELETE'])
    def delete_book(book_id):
        try:
            book = Book.query.filter(Book.id == book_id).one_or_none()

            if book is None:
                abort(404)

            book.delete()
            books = Book.query.all()
            pagination = paginate_books(books)

            return jsonify({
                'success': True,
                'deleted': book.id,
                'books': pagination,
                'total_books': len(books)
            })

        except:
            abort(422)
        # for testing DELETE: curl -X DELETE http://127.0.0.1:5000/books/10

    @app.route('/books', methods=['POST'])
    def create_book():

        body = request.get_json()
        new_title = body.get('title', None)
        new_author = body.get('author', None)
        new_rating = body.get('rating', None)

        try:
            book = Book(title=new_title, author=new_author, rating=new_rating)

            book.insert()
            books = Book.query.all()
            pagination = paginate_books(books)

            return jsonify({
                'success': True,
                'created': book.id,
                'books': pagination,
                'total_books': len(books)
            })

        except:
            abort(405)
        # for testing POST: curl -X POST -H "Content-Type: application/json" -d '{"title":"Harry Potter", "author":"Joanne K. Rowling", "rating":"8"}' http://127.0.0.1:5000/books

    @app.route('/books/search', methods=['POST'])
    def search_book_title():
        body = request.get_json()
        search_term = body.get('search_term')

        try:
            suggestions = Book.query.filter(
                Book.title.ilike(f'%{search_term}%')).all()

            if not suggestions:
                abort(404)

            return jsonify({
                'success': True,
                'suggestions': paginate_books(suggestions),
                'total_books': len(suggestions)
            })
        except:
            abort(404)
        # for testing: curl -X POST -H "Content-Type: application/json" -d '{"search_term":"an"}' http://127.0.0.1:5000/books/search

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad request"
        }), 400

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(405)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 405,
            "message": "method not allowed"
        }), 405

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    return app
Example #18
0
import os
from flask import Flask, request, abort, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
import random
import json
from models import setup_db, Question, Category,db

QUESTIONS_PER_PAGE = 10


app = Flask(__name__)
# create and configure the app
cors=CORS(app)
setup_db(app)



@app.route("/questions",methods=["GET"])
def questions_get():
  pagenum=dict(request.args)["page"]
  questions=[]
  categores={}
  for q in list(db.session.query(Question).all()):
    questions.append({"id":q.id,
                      "question":q.question,
                      "answer":q.answer,
                      "category":q.category,
                      "difficulty":q.difficulty})  
  for c in db.session.query(Category).all():
    categores[c.id]=c.type
Example #19
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)
    '''
    @DONE: Set up CORS. Allow '*' for origins. Delete the sample route after
    completing the TODOs
    '''
    cors = CORS(app, resources={r"/*": {"origins": "*"}})
    '''
    @DONE: Use the after_request decorator to set Access-Control-Allow
    '''

    # CORS Headers
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PUT,POST,DELETE,OPTIONS')
        return response

    '''
    @DONE:
    Create an endpoint to handle GET requests
    for all available categories.
    '''

    @app.route('/categories')
    def retrieve_categories():
        categories = Category.query.order_by(Category.id).all()
        category_list = {category.id: category.type for category in categories}

        if len(categories) == 0:
            abort(404)

        return jsonify({
            'success': True,
            'categories': category_list,
            'total_categories': len(Category.query.all()),
        })

    '''
    @DONE:
    Create an endpoint to handle GET requests for questions,
    including pagination (every 10 questions).
    This endpoint should return a list of questions,
    number of total questions, current category, categories.

    TEST: At this point, when you start the application
    you should see questions and categories generated,
    ten questions per page and pagination at the bottom of the screen
    for three pages.
    Clicking on the page numbers should update the questions.
    '''

    @app.route('/questions')
    def retrieve_questions():
        questions = Question.query.order_by(Question.id).all()
        current_questions = paginate_questions(request, questions)
        categories = Category.query.all()
        category_list = {category.id: category.type for category in categories}
        if len(current_questions) == 0:
            abort(404)

        return jsonify({
            'success': True,
            'questions': current_questions,
            'total_questions': len(Question.query.all()),
            'categories': category_list
        })

    '''
    @DONE:
    Create an endpoint to DELETE question using a question ID.

    TEST: When you click the trash icon next to a question, the question will
    be removed.
    This removal will persist in the database and when you refresh the page.
    '''

    @app.route('/questions/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):
        try:
            question = Question.query.filter(
                Question.id == question_id).one_or_none()

            if question is None:
                abort(404)

            question.delete()
            selection = Question.query.order_by(Question.id).all()
            current_questions = paginate_questions(request, selection)

            return jsonify({
                'success': True,
                'deleted': question_id,
                'questions': current_questions,
                'total_questions': len(Question.query.all())
            })
        except:
            abort(422)

    '''
    @DONE:
    Create an endpoint to POST a new question,
    which will require the question and answer text,
    category, and difficulty score.

    TEST: When you submit a question on the "Add" tab,
    the form will clear and the question will appear at the end of the
    last page of the questions list in the "List" tab.
    '''
    '''&'''
    '''
    @DONE:
    Create a POST endpoint to get questions based on a search term.
    It should return any questions for whom the search term
    is a substring of the question.

    TEST: Search by any phrase. The questions list will update to include
    only question that include that string within their question.
    Try using the word "title" to start.
    '''

    @app.route('/questions', methods=['POST'])
    def create_question():
        body = request.get_json()
        question = body.get('question', None)
        answer = body.get('answer', None)
        category = body.get('category', None)
        difficulty = body.get('difficulty', None)
        search = body.get('searchTerm', None)
        try:
            # if json body contains no search, a new question will be created
            if not search:
                if question is None or answer is None \
                        or category is None or difficulty is None:
                    abort(422)

                new_question = Question(question=question,
                                        answer=answer,
                                        category=category,
                                        difficulty=difficulty)
                new_question.insert()

                selection = Question.query.order_by(Question.id).all()
                current_questions = paginate_questions(request, selection)

                return jsonify({
                    'success': True,
                    'created': new_question.id,
                    'questions': current_questions,
                    'total_questions': len(Question.query.all())
                })
            else:
                # If the json request contains search, a search will be
                # implemented
                selection = Question.query.order_by(Question.id).filter(
                    Question.question.ilike(f'%{search}%'))
                current_questions = paginate_questions(request, selection)
                return jsonify({
                    'success': True,
                    'questions': current_questions,
                    'total_questions': len(selection.all())
                })
        except:
            abort(422)

    '''
    @DONE:
    Create a GET endpoint to get questions based on category.

    TEST: In the "List" tab / main screen, clicking on one of the
    categories in the left column will cause only questions of that
    category to be shown.
    '''

    @app.route('/categories/<int:category_id>/questions')
    def get_category_questions(category_id):
        selection = Question.query.order_by(
            Question.id).filter(Question.category == category_id)
        current_questions = paginate_questions(request, selection)
        current_category = Category.query.get(category_id)

        if len(current_questions) == 0:
            abort(404)

        return jsonify({
            'success': True,
            'questions': current_questions,
            'total_questions': len(current_questions),
            'current_category': current_category.type
        })

    '''
    @DONE:
    Create a POST endpoint to get questions to play the quiz.
    This endpoint should take category and previous question parameters
    and return a random questions within the given category,
    if provided, and that is not one of the previous questions.

    TEST: In the "Play" tab, after a user selects "All" or a category,
    one question at a time is displayed, the user is allowed to answer
    and shown whether they were correct or not.
    '''

    @app.route('/quizzes', methods=['POST'])
    def retrieve_quizzes():
        body = request.get_json()
        previous_questions = body.get('previous_questions', None)
        quiz_category = body.get('quiz_category', None)

        if previous_questions is None or quiz_category is None:
            abort(422)

        # Get questions either by category or all
        if quiz_category['id'] != 0:
            questions = Question.query \
                .filter(Question.category == quiz_category['id']) \
                .filter(~Question.id.in_(previous_questions))
        else:
            questions = Question.query \
                .filter(~Question.id.in_(previous_questions))

        if not questions:
            abort(404)

        # Get a list of all the filtered IDs in order to select a random
        # number from it
        random_list = [question.id for question in questions]
        if len(random_list) == 0:
            return jsonify({'result': True})
        random_id = random.choice(random_list)
        # Select one random question against the random list
        question = Question.query.get(random_id)

        return jsonify({
            'success': True,
            'question': question.format(),
        })

    '''
    @DONE:
    Create error handlers for all expected errors
    including 404 and 422.
    '''

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad request"
        }), 400

    @app.errorhandler(500)
    def internal_error(error):
        return jsonify({"success": False, "error": 500, "message": error}), 500

    def view(request):
        raise NotFound()

    @responder
    def application(environ, start_response):
        request = BaseRequest(environ)
        try:
            return view(request)
        except NotFound as e:
            return not_found(request)
        except HTTPException as e:
            return e

    return app
Example #20
0
def create_app(test_config=None):
    app = Flask(__name__,static_folder='./my-react-app/build', static_url_path='/')
    setup_db(app)
    CORS(app)


    @app.route('/')  
    def index():
        return app.send_static_file('index.html')

    @app.route("/drinks", methods=["GET"])
    @cross_origin()
    def get_all_drinks():
        drinks = Drink.query.all()
        
        try:
            return (
                json.dumps(
                    {"success": True, "drinks": [drink.title for drink in drinks]}
                ),
                200
            )
        except:
            abort(400)

    @app.route("/post-drinks", methods=["POST"])
    @cross_origin()
    @requires_auth("post:drinks")
    def drink_post(jwt):
        body = dict(request.form or request.json or request.data)
        new_drink_title = body.get("title", None)
        new_recipe_drink = body.get("recipe", None)
        if new_drink_title is  '':
            abort(422)
        try:
            drink = Drink(title=new_drink_title, recipe=json.dumps([new_recipe_drink]))           
            drink.insert()
            return(
                 json.dumps({"success": True, "newly_created_drink": drink.long()}), 200)          
        except Exception:
            abort(422)

    @app.route("/drinks-detail", methods=["GET"])
    @cross_origin()
    @requires_auth("get:drinks-detail")
    def drinks_detail(jwt):
        drinks = Drink.query.all()
        try:
            return (
                json.dumps(
                    {"success": True, "drinks": [drink.long() for drink in drinks]}
                ),
                200,
            )
        except Exception:
            abort(400)


    @app.route("/drinks-update/<int:id>", methods=["PATCH"])
    @cross_origin()
    @requires_auth("patch:drinks")
    def update_drinks(jwt, id):
            id = id
            drink = Drink.query.filter(Drink.id==id).one_or_none()

            if drink is None:
                abort(404)
            try:
                body = dict(request.form or request.json or request.data)
                updated_recipe = body.get("recipe", None)
                updated_title = body.get("title", None)
                if updated_recipe:
                    drink.recipe = json.dumps(updated_recipe)
                if updated_title:
                    drink.title = updated_title
                drink.update()

                return (json.dumps({"success": True, "drinks": drink.long()}), 200)

            except Exception:
                abort(422)


    @app.route("/drinks-delete/<int:drink_id>", methods=["DELETE"])
    @cross_origin()
    @requires_auth("delete:drinks")
    def delete_drink(jwt, drink_id):
       
        drink = Drink.query.filter(Drink.id ==drink_id).one_or_none()

        if drink is None:
            abort(404)
        else:     
            try:
                drink.delete()

                return( json.dumps(
                        {
                            "success": True,
                            "deleted": drink.id,
                        }),200)  
            except Exception:
                abort(400)

    ## Error Handling

    @app.errorhandler(404)
    def not_found(error):
        return app.send_static_file('index.html')

    @app.errorhandler(422)
    def unprocessable(error):
        return(
            json.dumps({"success": False, "error": 422, "message": "unprocessable"}),
            422)
        
    @app.errorhandler(400)
    def bad_request(error):
        return( 
            json.dumps({"success": False, "error": 400, "message": "bad request"}),
         400)

    @app.errorhandler(500)
    def internal_service_error(error):
        return(
            json.dumps(
                {"success": False, "error": 500, "message": "internal server error"}),
            500)
       
    @app.errorhandler(401)
    def unauthorized_error(error):
        return (
            json.dumps(
                {"success": False, "error": 401, "message": "unauthorized"}),
            401)   

    @app.errorhandler(AuthError)
    def auth_error(error):
        response = jsonify(error.error)
        response.status_code = error.status_code
        return response

    return app
Example #21
0
def create_app(test_config=None):
    """Create and configure the app."""
    app = Flask(__name__)
    setup_db(app)
    CORS(app, resources={r"*": {"origins": "*"}})

    # CORS Headers
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type:application/json, Authorization')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET, POST, PATCH, DELETE, OPTIONS')
        return response

    def get_error_message(error, default_text):
        """Get error messages."""
        try:
            return error.description['message']
        except:
            return default_text

    @app.route('/')
    def landing_page():
        return "Welcome to the Casting Agency!"

    @app.route('/actors', methods=['GET'])
    @requires_auth('get:actors')
    def get_actors(token):
        """Return a list of actors."""
        actors = Actor.query.order_by(Actor.id).all()
        current_actors = pagination(request, actors)

        if len(current_actors) == 0:
            abort(404, {'message': 'No Actors Found In Database'})

        result = {'success': True, 'current_actors': current_actors}
        return jsonify(result)

    @app.route('/actors', methods=['POST'])
    @requires_auth('post:actors')
    def create_actors(token):
        """Create a new Actor."""
        body = request.get_json()

        if not body:
            abort(404,
                  {'message', 'Request does not contain a valid JSON body'})

        name = body.get('name', None)
        age = body.get('age', None)
        gender = body.get('gender', 'Other')

        if not name:
            abort(422, {'message': 'No Name Provided'})

        if not age:
            abort(422, {'message': 'No Age Provided'})

        new_actor = (Actor(name=name, age=age, gender=gender))
        new_actor.insert()

        return jsonify({'success': True, 'created': new_actor.id})

    @app.route('/actors/<int:actor_id>', methods=['PATCH'])
    @requires_auth('patch:actors')
    def edit_actors(token, actor_id):
        """Edit actors."""
        body = request.get_json()

        if not actor_id:
            abort(400,
                  {'message': 'Please add an actor id to the requested url'})

        if not body:
            abort(400,
                  {'message': 'Request does not contain a vaild JSON body.'})

        actor_to_update = Actor.query.filter(
            Actor.id == actor_id).one_or_none()

        if not actor_to_update:
            abort(
                404, {
                    'message':
                    'Actor with id {} not found in database.'.format(actor_id)
                })

        name = body.get('name', actor_to_update.name)
        age = body.get('age', actor_to_update.age)
        gender = body.get('gender', actor_to_update.gender)

        actor_to_update.name = name
        actor_to_update.age = age
        actor_to_update.gender = gender

        actor_to_update.update()

        return jsonify({
            'success': True,
            'updated': actor_to_update.id,
            'actor': [actor_to_update.format()]
        })

    @app.route('/actors/<int:actor_id>', methods=['DELETE'])
    @requires_auth('delete:actors')
    def delete_actor(token, actor_id):
        """Delete a Actor."""
        if not actor_id:
            abort(400,
                  {'message': 'Please add an actor id to the requested url'})

        actor_to_delete = Actor.query.filter(
            Actor.id == actor_id).one_or_none()

        if not actor_to_delete:
            abort(
                404, {
                    'message':
                    'Actor with id {} not found in datebase.'.format(actor_id)
                })

        actor_to_delete.delete()

        return jsonify({'success': True, 'deleted': actor_id})

    @app.route('/movies', methods=['GET'])
    @requires_auth('get:movies')
    def get_movies(token):
        """Get movies route."""
        selection = Movie.query.order_by(Movie.id).all()
        paginated_movies = pagination(request, selection)

        if len(paginated_movies) == 0:
            abort(404, {'message': 'No movies found in database.'})

        return jsonify({'success': True, 'movies': paginated_movies})

    @app.route('/movies', methods=['POST'])
    @requires_auth('post:movies')
    def create_movies(token):
        """Create movies route."""
        if request.data:
            body = request.get_json()

            if not body:
                abort(
                    400,
                    {'message': 'Request does not contain a vaild JSON body'})

            title = body.get('title', None)
            release_date = body.get('release_date', None)

            if not title:
                abort(422, {'message': 'No title provided'})

            if not release_date:
                abort(422, {'message': 'No "release_date" provided'})

            new_movie = (Movie(title=title, release_date=release_date))
            new_movie.insert()

            return jsonify({'success': True, 'created': new_movie.id})
        else:
            abort(422)

    @app.route('/movies/<int:movie_id>', methods=['PATCH'])
    @requires_auth('patch:movies')
    def edit_movies(token, movie_id):
        """Edit movies method."""
        body = request.get_json()

        if not movie_id:
            abort(400, {
                'message': 'Please add a valid movie ID to the requested url'
            })

        if not body:
            abort(400,
                  {'message': 'Request does not contain a vaild JSON body'})

        movie_to_update = Movie.query.filter(
            Movie.id == movie_id).one_or_none()

        if not movie_to_update:
            abort(
                404, {
                    'message':
                    'Movie with id {} not found in database.'.format(movie_id)
                })

        title = body.get('title', movie_to_update.title)
        release_date = body.get('release_date', movie_to_update.release_date)

        movie_to_update.title = title
        movie_to_update.release_date = release_date

        movie_to_update.update()

        return jsonify({
            'success': True,
            'edited': movie_to_update.id,
            'movie': [movie_to_update.format()]
        })

    @app.route('/movies/<int:movie_id>', methods=['DELETE'])
    @requires_auth('delete:movies')
    def delete_movies(token, movie_id):
        """Delete method for movies."""
        if not movie_id:
            abort(400,
                  {'message': 'Please add a movie id to the requested url'})

        movie_to_delete = Movie.query.filter(
            Movie.id == movie_id).one_or_none()

        if not movie_to_delete:
            abort(
                404, {
                    'message':
                    'Movie with id {} not found in database.'.format(movie_id)
                })

        movie_to_delete.delete()

        return jsonify({'success': True, 'deleted': movie_id})

        @app.errorhandler(404)
        def not_found(error):
            return jsonify({
                'success': False,
                'error': 404,
                'message': 'Resource Not Found'
            }), 404

        @app.errorhandler(422)
        def unprocessable(error):
            return jsonify({
                'success': False,
                'error': 422,
                'message': 'unprocessable'
            }), 422

        @app.errorhandler(400)
        def bad_request(error):
            return jsonify({
                "success": False,
                "error": 400,
                "message": "bad request"
            }), 400

    return app
Example #22
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)
    '''
    @TODO: Set up CORS. Allow '*' for origins. Delete the sample route after completing the TODOs
    '''
    CORS(app, resources={'/': {'origins': '*'}})
    '''
    @TODO: Use the after_request decorator to set Access-Control-Allow
    '''
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PUT,POST,DELETE,OPTIONS')
        response.headers.add('Access-Control-Allow-Origin', '*')
        return response

    '''
    @TODO: 
    Create an endpoint to handle GET requests 
    for all available categories.
    '''

    @app.route("/categories", methods=['GET'])
    def get_categories():
        selection = Category.query.all()
        if len(selection) == 0:
            abort(404)
        categories = {category.id: category.type for category in selection}
        return jsonify({
            'success': True,
            'categories': categories
            # [category.format() for category in selection],
        })

    '''
    @TODO: 
    Create an endpoint to handle GET requests for questions, 
    including pagination (every 10 questions). 
    This endpoint should return a list of questions, 
    number of total questions, current category, categories. 

    TEST: At this point, when you start the application
    you should see questions and categories generated,
    ten questions per page and pagination at the bottom of the screen for three pages.
    Clicking on the page numbers should update the questions. 
    '''

    @app.route("/questions", methods=['GET'])
    def get_questions():
        selection = Question.query.order_by(Question.id).all()
        current_questions = paginate_questions(request, selection)
        category_selection = Category.query.all()
        categories = {
            category.id: category.type
            for category in category_selection
        }
        if len(current_questions) == 0:
            abort(404)
        return jsonify({
            'success': True,
            'questions': current_questions,
            'totalQuestions': len(Question.query.all()),
            'categories': categories
        })

    '''
    @TODO: 
    Create an endpoint to DELETE question using a question ID. 

    TEST: When you click the trash icon next to a question, the question will be removed.
    This removal will persist in the database and when you refresh the page. 
    '''

    @app.route("/questions/<int:question_id>", methods=['DELETE'])
    def delete_question(question_id):
        try:
            question = Question.query.filter(
                Question.id == question_id).one_or_none()
            if question is None:
                abort(404)

            question.delete()
            return jsonify({'success': True, 'question_id': question_id})
        except Exception:
            abort(422)

    '''
    @TODO: 
    Create an endpoint to POST a new question, 
    which will require the question and answer text, 
    category, and difficulty score.

    TEST: When you submit a question on the "Add" tab, 
    the form will clear and the question will appear at the end of the last page
    of the questions list in the "List" tab.  
    '''

    @app.route("/questions", methods=['POST'])
    def create_question():
        body = request.get_json()
        if body.get('question') and body.get('answer') and body.get(
                'category') and body.get('difficulty'):
            new_question_string = body.get('question')
            new_answer_string = body.get('answer')
            new_category_string = body.get('category')
            new_difficulty_string = body.get('difficulty')

            try:
                new_question = Question(question=new_question_string,
                                        answer=new_answer_string,
                                        category=new_category_string,
                                        difficulty=new_difficulty_string)
                new_question.insert()

                selection = Question.query.order_by(Question.id).all()
                current_questions = paginate_questions(request, selection)

                return jsonify({
                    'success': True,
                    'created': new_question.id,
                    'questions': current_questions,
                    'total_questions': len(Question.query.all())
                })
            except Exception as error:
                abort(422)

        elif body.get('searchTerm'):
            try:
                phrase = body.get('searchTerm')
                search_phrase = "%{0}%".format(phrase)
                selection = Question.query.filter(
                    Question.question.ilike(search_phrase)).all()
                current_questions = paginate_questions(request, selection)
                return jsonify({
                    'success': True,
                    'questions': current_questions,
                    'total_questions': len(selection)
                })
            except Exception as error:
                abort(422)

        else:
            abort(422)

    '''
    @TODO: 
    Create a POST endpoint to get questions based on a search term. 
    It should return any questions for whom the search term 
    is a substring of the question. 

    TEST: Search by any phrase. The questions list will update to include 
    only question that include that string within their question. 
    Try using the word "title" to start. 
    '''
    '''
    @TODO: 
    Create a GET endpoint to get questions based on category. 

    TEST: In the "List" tab / main screen, clicking on one of the 
    categories in the left column will cause only questions of that 
    category to be shown. 
    '''

    @app.route("/categories/<int:category_id>/questions", methods=['GET'])
    def get_questions_by_category(category_id):
        selection = Question.query.filter(
            Question.category == category_id).all()
        current_questions = paginate_questions(request, selection)

        if len(selection) == 0:
            abort(404)
        return jsonify({
            'success': True,
            'category': category_id,
            'questions': current_questions,
            'total_questions': len(Question.query.all())
        })

    '''
    @TODO: 
    Create a POST endpoint to get questions to play the quiz. 
    This endpoint should take category and previous question parameters 
    and return a random questions within the given category, 
    if provided, and that is not one of the previous questions. 

    TEST: In the "Play" tab, after a user selects "All" or a category,
    one question at a time is displayed, the user is allowed to answer
    and shown whether they were correct or not. 
    '''

    @app.route('/quizzes', methods=['POST'])
    def get_quiz_question():
        try:
            body = request.get_json()

            previous_questions = body.get('previous_questions', None)
            category = body.get('quiz_category', None)

            if category is None:
                abort(422)
            category_id = int(category['id'])

            if category_id == 0:
                questions = Question.query.order_by(Question.id).all()
            else:
                questions = Question.query.filter(
                    Question.category == int(category_id)).all()

            if previous_questions is not None:
                if len(previous_questions) == len(questions):
                    return jsonify({"success": True})

            def get_random_question(questions_possible):
                return questions_possible[random.randint(
                    0,
                    len(questions) - 1)]

            if previous_questions == [] or previous_questions is None:
                question = get_random_question(questions)
            else:
                question = get_random_question(questions)
                while question.id in previous_questions:
                    question = get_random_question(questions)

            print(question.format())
            return jsonify({"success": True, "question": question.format()})
        except Exception as error:
            abort(400)

    '''
    @TODO: 
    Create error handlers for all expected errors 
    including 404 and 422. 
    '''

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad request"
        }), 400

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            'success': False,
            'error': 404,
            'message': 'resource not found'
        }), 404

    @app.errorhandler(422)
    def not_found(error):
        return jsonify({
            'success': False,
            'error': 422,
            'message': 'unproccessable'
        }), 422

    return app
Example #23
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)

    # DONE: Set up CORS. Allow '*' for origins. Delete the sample route
    # after completing the TODOs
    CORS(app, resources={r"/api/*": {"origins": "*"}})

    # DONE: Use the after_request decorator to set Access-Control-Allow
    @app.after_request
    def after_request(response):
        response.headers.add("Access-Control-Allow-Headers",
                             "Content-Type, Authorization, true")
        response.headers.add("Access-Control-Allow-Headers",
                             "GET, PATCH, POST, DELETE, OPTIONS")
        return response

    # DONE: Create an endpoint to handle GET requests for all available
    # categories.
    @app.route("/api/categories", methods=["GET"])
    def retrieve_categories():
        try:
            return jsonify({
                "success": True,
                "categories": format_categories(),
            })
        except Exception:
            abort(500)

    # DONE: Create an endpoint to handle GET requests for questions,
    # including pagination (every 10 questions).
    # This endpoint should return a list of questions,
    # number of total questions, current category, categories.
    # TEST: curl localhost:5000/questions
    @app.route("/api/questions", methods=["GET"])
    def retrieve_questions():
        selection = Question.query.all()
        current_questions = paginate_questions(request, selection)
        if not current_questions:
            abort(404)
        return jsonify({
            "success": True,
            "questions": current_questions,
            "total_questions": len(selection),
            "categories": format_categories(),
            "current_category": None
        })

    # TEST: At this point, when you start the application
    # you should see questions and categories generated,
    # ten questions per page and pagination at the bottom of the screen
    # for three pages.
    # Clicking on the page numbers should update the questions.

    # DEBUG route
    # TEST: curl localhost:5000/questions/4 -X GET
    @app.route("/api/questions/<int:question_id>", methods=["GET"])
    def retrieve_question(question_id):
        try:
            question = Question.query.filter(
                Question.id == question_id).one_or_none()
            if not question:
                abort(404)
            return jsonify({
                "success": True,
                "questions": question.format(),
                "current_category": None
            })
        except Exception:
            abort(422)

    # DONE: Create an endpoint to DELETE question using a question ID.
    # TEST: curl localhost:5000/questions/5 -X DELETE
    @app.route("/api/questions/<int:question_id>", methods=["DELETE"])
    def delete_question(question_id):
        try:
            question = Question.query.filter(
                Question.id == question_id).one_or_none()
            if not question:
                abort(404)
            question.delete()
            selection = Question.query.all()
            current_questions = paginate_questions(request, selection)
            return jsonify({
                "success": True,
                "questions": current_questions,
                "total_questions": len(selection),
                "categories": format_categories(),
                "current_category": None,
                "deleted": question_id
            })
        except Exception:
            abort(404)

    # TEST: When you click the trash icon next to a question, the question will
    # be removed.
    # This removal will persist in the database and when you refresh the page.

    # DONE: Create an endpoint to POST a new question,
    # which will require the question and answer text,
    # category, and difficulty score.
    # DONE: Create a POST endpoint to get questions based on a search term.
    # It should return any questions for whom the search term
    # is a substring of the question.
    @app.route("/api/questions", methods=["POST"])
    def add_question():
        form_data = request.json
        if "searchTerm" in form_data:
            search_term = form_data["searchTerm"].strip()
            questions = Question.query.filter(
                Question.question.ilike(f"%{search_term}%")).all()
            current_questions = [q.format() for q in questions]
            return jsonify({"success": True, "questions": current_questions})
        else:
            if (form_data['question'].strip()
                    == "") or (form_data["answer"].strip() == ""):
                abort(400)
            try:
                new_question = Question(question=form_data['question'].strip(),
                                        answer=form_data['answer'].strip(),
                                        category=form_data['category'],
                                        difficulty=form_data['difficulty'])
                new_question.insert()
            except Exception:
                abort(422)

            return jsonify({"success": True, "added": new_question.id})

    # TEST: When you submit a question on the "Add" tab,
    # the form will clear and the question will appear at the end of the last
    # page of the questions list in the "List" tab.
    # TEST: Search by any phrase. The questions list will update to include
    # only question that include that string within their question.
    # Try using the word "title" to start.

    # TODO: Create a GET endpoint to get questions based on category.
    @app.route('/api/categories/<int:category_id>/questions')
    def get_category_questions(category_id):
        questions = Question.query.filter_by(category=str(category_id)).all()
        current_questions = paginate_questions(request, questions)
        if not current_questions:
            abort(404)
        return jsonify({
            'success': True,
            'questions': current_questions,
            'total_questions': len(questions),
            'categories': Category.query.get(category_id).format(),
            'current_category': category_id
        })

    # TEST: In the "List" tab / main screen, clicking on one of the
    # categories in the left column will cause only questions of that
    # category to be shown.

    # DONE: Create a POST endpoint to get questions to play the quiz.
    # This endpoint should take category and previous question parameters
    # and return a random questions within the given category,
    # if provided, and that is not one of the previous questions.
    @app.route('/api/quizzes', methods=['POST'])
    def play():
        request_data = request.json
        try:
            request_cat = request_data['quiz_category']['id']
        except Exception:
            abort(400)
        if request_cat == 0:
            questions = Question.query.all()
        else:
            questions = Question.query.filter_by(
                category=str(request_cat)).all()
        questions = [x.format() for x in questions]
        # Remove questions that have been already asked
        try:
            previous_questions = request_data['previous_questions']
        except Exception:
            abort(400)
        fresh_questions = []
        for question in questions:
            if question['id'] not in previous_questions:
                fresh_questions.append(question)
        # Make sure not all the questions were asked
        # If so, return nothing to tell the frontend that the game is over
        if not fresh_questions:
            return jsonify({'success': True})
        question = random.choice(fresh_questions)
        return jsonify({'success': True, 'question': question})

    # TEST: In the "Play" tab, after a user selects "All" or a category,
    # one question at a time is displayed, the user is allowed to answer
    # and shown whether they were correct or not.

    # DONE: Create error handlers for all expected errors
    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "Bad Request"
        })

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "Not found"
        })

    @app.errorhandler(422)
    def unprocessable_entity(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "Unprocessable Entity"
        })

    @app.errorhandler(500)
    def server_error(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "Internal Server Error"
        })

    return app
Example #24
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)
    '''
  @TODO: Set up CORS. Allow '*' for origins. Delete the sample route after completing the TODOs
  '''
    #Default CORS origin is *
    CORS(app)
    '''
  @TODO: Use the after_request decorator to set Access-Control-Allow
  '''
    @app.after_request
    def after_request(response):
        response.headers['Access-Control-Allow'] = '*'
        return response

    '''
  @TODO: 
  Create an endpoint to handle GET requests 
  for all available categories.
  '''

    @app.route("/categories")
    def get_categories():

        # Query all categories
        categories = Category.query.all()

        # Reformat categories into a dictionary
        # of id: type
        categories_ids = {
            category.id: category.type
            for category in categories
        }

        result = jsonify({'success': True, 'categories': categories_ids})

        return result

    '''
  @TODO: 
  Create an endpoint to handle GET requests for questions, 
  including pagination (every 10 questions). 
  This endpoint should return a list of questions, 
  number of total questions, current category, categories. 

  TEST: At this point, when you start the application
  you should see questions and categories generated,
  ten questions per page and pagination at the bottom of the screen for three pages.
  Clicking on the page numbers should update the questions. 
  '''

    # Create pagination function called in get_questions
    def paginate(questions, max_per_page, page):
        start = (page - 1) * max_per_page
        end = page * max_per_page

        questions = questions[start:end]

        return questions

    @app.route("/questions")
    def get_questions():

        # Get page number from request
        page = request.args.get('page', default=1)
        page = int(page)

        # Query all questions from database and format
        questions = Question.query.all()
        questions = [question.format() for question in questions]

        # Calculate total length of request to support pagination
        max_questions = len(questions)

        # Run paginate custom function
        questions = paginate(questions, QUESTIONS_PER_PAGE, page)

        # Get all categories
        categories = Category.query.all()
        categories_ids = {
            category.id: category.type
            for category in categories
        }

        result = {
            'success': True,
            'questions': questions,
            'total_questions': max_questions,
            'categories': categories_ids,
            'currentCategory': None
        }

        return jsonify(result)

    '''
  @TODO: 
  Create an endpoint to DELETE question using a question ID. 

  TEST: When you click the trash icon next to a question, the question will be removed.
  This removal will persist in the database and when you refresh the page. 
  '''

    @app.route("/questions/<int:id>", methods=['DELETE'])
    def delete_question(id):

        question = Question.query.filter(Question.id == id).first()

        if question is None:
            abort(404)

        try:
            question.delete()
        except Exception as e:
            abort(500)

        result = jsonify({'success': True})
        return result

    '''
  @TODO: 
  Create an endpoint to POST a new question, 
  which will require the question and answer text, 
  category, and difficulty score.

  TEST: When you submit a question on the "Add" tab, 
  the form will clear and the question will appear at the end of the last page
  of the questions list in the "List" tab.  
  '''

    @app.route("/questions", methods=['POST'])
    def create_question():

        body = request.get_json()

        # Make sure all keys are in the request
        form_keys = ['question', 'answer', 'difficulty', 'category']
        if not all(form_key in body for form_key in form_keys):
            abort(400)

        try:
            q = Question(question=body['question'],
                         answer=body['answer'],
                         difficulty=body['difficulty'],
                         category=body['category'])
            q.insert()
        except Exception as e:
            db.session.rollback()
            print(e)

        result = jsonify({'success': True})
        return result

    '''
  @TODO: 
  Create a POST endpoint to get questions based on a search term. 
  It should return any questions for whom the search term 
  is a substring of the question. 

  TEST: Search by any phrase. The questions list will update to include 
  only question that include that string within their question. 
  Try using the word "title" to start. 
  '''

    @app.route("/questions/search", methods=['POST'])
    def search_questions():
        #Get search term
        body = request.get_json()
        search_term = body['searchTerm']

        # Find and format questions with the search team, case insensitive
        questions = Question.query.filter(
            Question.question.ilike('%{}%'.format(search_term))).all()
        questions = [question.format() for question in questions]

        result = {
            'success': True,
            'questions': questions,
            'totalQuestions': len(questions),
            'currentCategory': None
        }

        return jsonify(result)

    '''
  @TODO: 
  Create a GET endpoint to get questions based on category. 

  TEST: In the "List" tab / main screen, clicking on one of the 
  categories in the left column will cause only questions of that 
  category to be shown. 
  '''

    @app.route('/categories/<id>/questions')
    def question_category(id):
        category_id = id

        questions = Question.query.filter(
            Question.category == category_id).all()
        questions = [question.format() for question in questions]

        result = {
            'success': True,
            'questions': questions,
            'totalQuestions': len(questions),
            'currentCategory': None
        }

        return jsonify(result)

    '''
  @TODO: 
  Create a POST endpoint to get questions to play the quiz. 
  This endpoint should take category and previous question parameters 
  and return a random questions within the given category, 
  if provided, and that is not one of the previous questions. 

  TEST: In the "Play" tab, after a user selects "All" or a category,
  one question at a time is displayed, the user is allowed to answer
  and shown whether they were correct or not. 
  '''

    @app.route('/quizzes', methods=['POST'])
    def play_quiz():

        body = request.get_json()

        # Category is object with type: string, id: int
        category = body['quiz_category']
        previous_questions = body['previous_questions']

        #Get all questions in category
        questions = Question.query.filter(Question.category == category['id'])

        # Get full list of question ids in the category
        question_ids = []
        for q in questions:
            question_ids.append(q.id)

        # Remove question ids if in previous questions list
        # Informed by list comprehension in following Stack Overflow answer:
        # https://stackoverflow.com/questions/4211209/remove-all-the-elements-that-occur-in-one-list-from-another/4211228

        potential_question_ids = [
            id for id in question_ids if id not in previous_questions
        ]

        # Get random question from potential question ids
        if len(potential_question_ids) > 0:
            random_question_id = random.choice(potential_question_ids)

            for q in questions:
                if q.id == random_question_id:
                    random_question = q.format()
        else:
            random_question = None

        result = {'success': True, 'question': random_question}

        return jsonify(result)

    '''
  @TODO: 
  Create error handlers for all expected errors 
  including 404 and 422. 
  400, 404, 422 and 500
  '''

    @app.errorhandler(405)
    def method_not_allowed(e):
        return jsonify({
            'success': False,
            'error': 405,
            'message': 'Method not allowed'
        }), 405

    @app.errorhandler(500)
    def server_error(e):
        return jsonify({
            'success': False,
            'error': 500,
            'message': 'Internal server error'
        }), 500

    @app.errorhandler(422)
    def unprocessable_entity(e):
        return jsonify({
            'success':
            False,
            'error':
            422,
            'message':
            'Request was well formed but included semantic errors'
        }), 422

    @app.errorhandler(404)
    def not_found(e):
        return jsonify({
            'success': False,
            'error': 404,
            'message': 'Page not found'
        }), 404

    @app.errorhandler(400)
    def bad_request(e):
        return jsonify({
            'success': False,
            'error': 400,
            'message': 'Bad request'
        }), 400

    return app
Example #25
0
def create_app(test_config=None):
    app = Flask(__name__)
    CORS(app)
    setup_db(app)

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,authorization,True')
        response.headers.add('Acess-Control-Allow-Methods',
                             'GET,POST,PATCH,DELETE,OPTIONS')
        return response

    @app.route('/')
    def index():
        return 'Congrats'

    @app.route('/actors')
    @requires_auth('get:actors')
    def get_all_actors(payload):
        try:
            Actors = Actor.query.all()
            Actors = [actor.format() for actor in Actors]
            return (jsonify({'success': True, 'Actors': Actors}), 200)
        except:
            abort(401)

    @app.route('/movies')
    @requires_auth('get:movies')
    def get_all_movies(token):
        movies = Movie.query.all()
        movies = [movie.format() for movie in movies]
        return (jsonify({'success': True, 'Movies': movies}), 200)

    @app.route('/actors/<int:actor_id>', methods=['DELETE'])
    @requires_auth('delete:actors')
    def delete_actor(token, actor_id):
        try:
            x = Actor.query.filter(Actor.id == actor_id).one_or_none()
            if x is None:
                abort(404)
            x.delete()
            return (jsonify({'success': True, 'actor_id': actor_id}), 200)
        except:
            abort(422)

    @app.route('/movies/<int:id>', methods=['DELETE'])
    @requires_auth('delete:movies')
    def delete_movie(token, id):
        try:
            x = Movie.query.filter(Movie.id == id).one_or_none()
            if x is None:
                abort(404)
            x.delete()
            return (jsonify({'success': True, 'id': id}), 200)
        except:
            abort(422)

    @app.route('/actors', methods=['POST'])
    @requires_auth('post:actors')
    def post_actor(token):
        try:
            body = request.get_json(
            )  # fetch the body data from the request body
            requested_name = body.get('name')
            requested_age = body.get('age')
            requested_gender = body.get('gender')
            if requested_name is None:
                abort(422)
            new_actor = Actor(
                name=requested_name,
                age=requested_age,
                gender=requested_gender
            )  # add the new data to the table as a new record
            new_actor.insert()
            if body is None:
                abort(422)
            return (jsonify({'success': True, 'id': new_actor.id}), 200)
        except:
            abort(422)

    @app.route('/movies', methods=['POST'])
    @requires_auth('post:movies')
    def post_movie(token):
        try:
            body = request.get_json()
            requested_title = body.get('title')
            requested_release_date = body.get('release_date')
            requested_actor_id = body.get('actor_id')
            new_movie = Movie(
                title=requested_title,
                release_date=requested_release_date,
                actor_id=requested_actor_id
            )  # add the new data to the table as a new record
            new_movie.insert()
            if body is None:
                abort(422)
            return (jsonify({'success': True, 'movies': new_movie.id}), 200)
        except:
            abort(422)

    @app.route('/actors/<int:id>', methods=['PATCH'])
    @requires_auth('edit:actors')
    def edit_actors(token, id):
        body = request.get_json()  # fetch the body data from the request body
        to_be_updated_row = Actor.query.filter(Actor.id == id).one_or_none(
        )  # See if we have that id is in our Table ?
        if to_be_updated_row is None:
            abort(
                404
            )  # id   is Not found , we do not have that record in our table
        requested_name = body.get('name')
        requested_age = body.get('age')
        requested_gender = body.get('gender')
        if requested_name is not None:
            to_be_updated_row.name = requested_name
        if requested_age is not None:
            to_be_updated_row.age = requested_age
        if requested_gender is not None:
            to_be_updated_row.gender = requested_gender
        try:
            to_be_updated_row.update()
        except:
            abort(422)
        actors = Actor.query.filter(Actor.id == id).one_or_none()
        if actors is None:
            abort(404)  # The Record is not found
        return (jsonify({'success': True, 'Actor': to_be_updated_row.id}), 200)

    @app.route('/movies/<int:id>', methods=['PATCH'])
    @requires_auth('edit:movies')
    def edit_movies(token, id):
        body = request.get_json()  # fetch the body data from the request body
        to_be_updated_row_n = Movie.query.filter(Movie.id == id).one_or_none(
        )  # See if we have that id is in our Table ?
        if to_be_updated_row_n is None:
            abort(
                404
            )  # id   is Not found , we do not have that record in our table

        # add the new data to the table as a new record

        if body.get('title') is not None:
            to_be_updated_row_n.title = body.get('title')
        if body.get('release_date') is not None:
            to_be_updated_row_n.release_date = body.get('release_date')

        try:
            to_be_updated_row_n.update()
        except:
            abort(422)
        return (jsonify({
            'success': True,
            'Movies': to_be_updated_row_n.id
        }), 200)

    @app.errorhandler(422)
    def unprocessable(error):
        return (jsonify({
            'success': False,
            'error': 422,
            'message': 'unprocessable'
        }), 422)

    @app.errorhandler(400)
    def badrequest(error):
        return (jsonify({
            'success': False,
            'error': 400,
            'message': 'bad request'
        }), 400)

    @app.errorhandler(404)
    def not_found(error):
        return (jsonify({
            'success': False,
            'error': 404,
            'message': 'resource not found'
        }), 404)

    @app.errorhandler(401)
    def Unauthorized(error):
        return (jsonify({
            'success': False,
            'error': 401,
            'message': 'Unauthorized'
        }), 401)

    @app.errorhandler(500)
    def server_error(error):
        return (jsonify({
            'success': False,
            'error': 500,
            'message': 'Internal Server Error'
        }), 500)

    @app.errorhandler(AuthError)
    def handle_auth_error(ex):
        response = jsonify(ex.error)
        response.status_code = ex.status_code
        return (jsonify({
            'sucess': False,
            'error': response.status_code,
            'message': response
        }), response.status_code)

    return app
def create_app(test_config=None):
  app = Flask(__name__)
  setup_db(app)

  
#@TODO:Set up CORS. Allow '*' for origins, and Delete the sample route after completing the TODOs:
  CORS(app, resources={'/': {'origins': '*'}})
 
#Use the after_request decorator to set Access-Control-Allow:
  @app.after_request
  def after_request(response):
      response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization,true')
      response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
    
      return response  

#Create an endpoint to handle GET requests for all available categories:
  @app.route('/categories')
  def get_categories():
      categories = Category.query.all()
      categories_dict = {}

      for category in categories:
        categories_dict[category.id] = category.type

      if (len(categories_dict) == 0):
        abort(404)

      return jsonify({
        'success': True,
        'categories': categories_dict
        })
 

#Create an endpoint to handle GET requests for questions, including pagination (every 10 questions):
#This endpoint should return a list of questions,number of total questions, current category, categories: 
#TEST: At this point, when you start the application
#you should see questions and categories generated,
#ten questions per page and pagination at the bottom of the screen for three pages.
#Clicking on the page numbers should update the questions. 

  @app.route('/questions')
  def get_questions():
   selection = Question.query.all()
   total_questions = len(selection)
   current_questions = paginate_questions(request, selection)
   categories = Category.query.all()
   categories_dict = {}
   for category in categories:
       categories_dict[category.id] = category.type

   if (len(current_questions) == 0):
       abort(404)

   return jsonify({
     'success': True,
     'questions': current_questions,
     'total_questions': total_questions,
     'categories': categories_dict
           })


#Create an endpoint to DELETE question using a question ID:
#TEST: When you click the trash icon next to a question, the question will be removed.
#This removal will persist in the database and when you refresh the page. 

  @app.route('/questions/<int:id>', methods=['DELETE'])
  def delete_question(id):
        try:
            question = Question.query.filter_by(id=id).one_or_none()
            if question is None:
             abort(404)
            question.delete()

            return jsonify({
                'success': True,
                'deleted': id
            })

        except:
            abort(422)


#Handles POST requests for creating new questions and searching questions:
#Create an endpoint to POST a new question, which will require the question and answer text, 
#category, and difficulty score.
#TEST: When you submit a question on the "Add" tab, 
#the form will clear and the question will appear at the end of the last page
#of the questions list in the "List" tab.  

#Create a POST endpoint to get questions based on a search term. It should return any questions for whom the search term 
#is a substring of the question. 
#TEST: Search by any phrase. The questions list will update to include only question that include that string within their question. 
#Try using the word "title" to start. 
  
  @app.route('/questions', methods=['POST'])
  def post_question():
     body = request.get_json()

     if (body.get('searchTerm')):
         search_term = body.get('searchTerm')

         selection = Question.query.filter(
            Question.question.ilike(f'%{search_term}%')).all()

         if (len(selection) == 0):
              abort(404)

         paginated = paginate_questions(request, selection)

         return jsonify({
          'success': True,
          'questions': paginated,
          'total_questions': len(Question.query.all())
            })
     else:
          new_question = body.get('question')
          new_answer = body.get('answer')
          new_difficulty = body.get('difficulty')
          new_category = body.get('category')

          if((new_question is None)  or (new_answer is None)
              or (new_difficulty is None) or (new_category is None)):
                abort(422)

     try:
        question = Question(question=new_question, answer=new_answer,
        difficulty=new_difficulty, category=new_category)
        question.insert()
        selection = Question.query.order_by(Question.id).all()
        current_questions = paginate_questions(request, selection)

        return jsonify({
         'success': True,
         'created': question.id,
         'question_created': question.question,
         'questions': current_questions,
         'total_questions': len(Question.query.all())
                })

     except:
           abort(422)


# Create a GET endpoint to get questions based on category:
#TEST: In the "List" tab / main screen, clicking on one of the categories in the left column will cause only questions of that 
#category to be shown. 
  @app.route('/categories/<int:id>/questions')
  def get_questions_by_category(id):

    category = Category.query.filter_by(id=id).one_or_none()

    if (category is None):
         abort(400)

    selection = Question.query.filter_by(category=category.id).all()
    paginated = paginate_questions(request, selection)

    return jsonify({
      'success': True,
      'questions': paginated,
      'total_questions': len(Question.query.all()),
      'current_category': category.type
        })
  
#Create a POST endpoint to get questions to play the quiz. 
# This endpoint should take category and previous question parameters 
#and return a random questions within the given category, 
# if provided, and that is not one of the previous questions. 

#TEST: In the "Play" tab, after a user selects "All" or a category, one question at a time is displayed, the user is allowed to answer
#and shown whether they were correct or not. 

  @app.route('/quizzes', methods=['POST'])
  def get_random_quiz_question():

    body = request.get_json()
    previous = body.get('previous_questions')
    category = body.get('quiz_category')

    if ((category is None) or (previous is None)):
          abort(400)

    if (category['id'] == 0):
        questions = Question.query.all()

    else:
        questions = Question.query.filter_by(category=category['id']).all()

    total = len(questions)

#Picks a random question:
    def get_random_question():
        return questions[random.randrange(0, len(questions), 1)]

#Checks to see if question has already been used:
    def check_if_used(question):
        used = False
        for ques in previous:
            if (ques == question.id):
                used = True

        return used

    question = get_random_question()
    while (check_if_used(question)):
          question = get_random_question()

          if (len(previous) == total):

              return jsonify({
                    'success': True
                })

    return jsonify({
          'success': True,
          'question': question.format()
        })

  

#Create error handlers for all expected errors: 

  @app.errorhandler(400)
  def not_found(error):
      return jsonify({
        "success": False,
        "error": 400,
        "message": "Bad Request"
      }), 400


  @app.errorhandler(404)
  def not_found(error):
      return jsonify({
        "success": False,
        "error": 404,
        "message": "Resource Not Found"
      }), 404


  @app.errorhandler(422)
  def not_found(error):
      return jsonify({
        "success": False,
        "error": 422,
        "message": "Unprocessable"
      }), 422

  return app
        
        
        
        
    

    
Example #27
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)
    '''
  @TODO: DONE Set up CORS. Allow '*' for origins. 
  @TODO: Delete the sample route after completing the TODOs
  '''
    cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
    '''
  @TODO: DONE Use the after_request decorator to set Access-Control-Allow
  '''
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type, Authorization, true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET, POST, DELETE')
        return response

    '''
  @TODO: DONE. Works, imgs working 
  Create an endpoint to handle GET requests 
  for all available categories.
  '''
    #Get categories. FE: FormView #20 Categories
    @app.route('/categories', methods=['GET'])
    def get_categories():
        categories = Category.query.all()
        #categories = {category.id: category.type for category in all_categories}
        formatted_categories = {}  #dictionary
        for category in categories:
            formatted_categories[category.id] = category.type

        if len(categories) == 0:
            abort(404)  #resource not found

        return jsonify({
            "success": True,
            "categories": formatted_categories,
            "total_categories": len(categories)
        })

    '''
  @TODO: Done, Works.  
  Create an endpoint to handle GET requests for questions, 
  including pagination (every 10 questions). 
  This endpoint should return a list of questions, 
  number of total questions, current category, categories. 
    
  TEST: At this point, when you start the application
  you should see questions and categories generated,
  ten questions per page and pagination at the bottom of the screen for three pages.
  Clicking on the page numbers should update the questions. 
  '''

    #Get Questions. FE: QuestionView #24
    @app.route('/questions',
               methods=['GET'])  #Qview: /questions?page=${this.state.page}
    def get_question():
        page = request.args.get('page', 1, type=int)
        start = (page - 1) * 10
        end = start + 10
        questions = [question.format() for question in Question.query.all()]

        if len(questions) == 0:
            abort(404)

        else:
            #categories = {category.id: category.type for category in all_categories}
            categories = Category.query.all()
            formatted_categories = {}  #dictionary
            for category in categories:
                formatted_categories[category.id] = category.type

            return jsonify({
                "success": True,
                "questions": questions[start:end],
                "total_questions": len(questions),
                "categories": formatted_categories,
                "current_category": None
            })

    '''
  #@TODO: Done; Works
  Create an endpoint to DELETE question using a question ID. 

  TEST: When you click the trash icon next to a question, the question will be removed.
  This removal will persist in the database and when you refresh the page. 
  '''

    #Delete question; FE: Qview 105
    @app.route('/questions/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):
        #question_id = request.json.get('id') #id from QuestionView.js

        try:
            question = Question.query.filter(
                Question.id == question_id).one_or_none()

            if question is None:
                abort(404)  #resource not found

            question.delete()
            selection = Question.query.all()
            #current_questions = paginate_questions(request, selection)

            return jsonify({
                "success": True,
                "deleted": question_id,
                "total_questions": len(selection)
            })

        except Exception as e:
            print("Exception: ", e)
            print(sys.exc_info())
            abort(422)  #unprocessable

    '''
  @TODO: DONE works
  Create an endpoint to POST a new question, which will require the question and answer text, 
  category, and difficulty score.

  TEST: When you submit a question on the "Add" tab, 
  the form will clear and the question will appear at the end of the last page
  of the questions list in the "List" tab.  
  '''

    #Add new question; FE: FormView #37. ToDo: invalidate if info missing
    @app.route('/questions/add', methods=['POST'])
    def submit_question():
        #From form: question, answer, difficulty, category
        #body, etc. based on books example

        data = request.get_json()  #replace body w data for consistency

        new_question = data.get('question')
        new_answer = data.get('answer')
        new_difficulty = data.get('difficulty')
        new_category = data.get('category')

        #Note: category type or id. id is int, type is string

        try:
            add_question = Question(question=new_question,
                                    answer=new_answer,
                                    category=new_category,
                                    difficulty=new_difficulty)

            add_question.insert()

            return jsonify({
                "success": True,
                "question": new_question,
                "answer": new_answer,
                "difficulty": new_difficulty,
                "category": new_category
            })

        except Exception as e:
            print('Exception is >> ', e)
            print(sys.exc_info())
            abort(422)

    '''
  @TODO: DONE *Working on backend & frontend!!!
  Create a POST endpoint to get questions based on a search term. 
  It should return any questions for whom the search term 
  is a substring of the question. 

  TEST: Search by any phrase. The questions list will update to include 
  only question that include that string within their question. 
  Try using the word "title" to start. 
  '''
    #Search questions
    @app.route('/questions/search', methods=['POST'])
    def submit_search():
        search_term = request.json.get('searchTerm', None)
        questions = Question.query.filter(
            Question.question.ilike('%{}%'.format(search_term))).all()
        formatted_questions = [question.format() for question in questions]

        if len(questions) == 0:
            formatted_questions = []
            abort(404)

        return jsonify({
            "success": True,
            "questions": formatted_questions,
            "total_questions": len(questions),
            "current_category": None
        })

    '''
  @TODO: DONE *works; c.f. questions end point
  Create a GET endpoint to get questions based on category. 

  TEST: In the "List" tab / main screen, clicking on one of the 
  categories in the left column will cause only questions of that 
  category to be shown. 
  '''
    #Get questions by category
    @app.route('/categories/<int:category_id>/questions', methods=['GET'])
    def get_by_category(category_id):

        questions = Question.query.filter(
            Question.category == str(category_id)).all()
        formatted_questions = [question.format() for question in questions]

        if len(questions) == 0:
            abort(404)  #resource not found

        else:
            return jsonify({
                "success": True,
                "questions": formatted_questions,
                "total_questions": len(Question.query.all()),
                "current_category": category_id
            })

    '''
  @TODO: DONE, working
  Create a POST endpoint to get questions to play the quiz. 
  This endpoint should take category and previous question parameters 
  and return a random questions within the given category, 
  if provided, and that is not one of the previous questions. 

  TEST: In the "Play" tab, after a user selects "All" or a category,
  one question at a time is displayed, the user is allowed to answer
  and shown whether they were correct or not. 
  '''
    #Quiz - questions to play; FE: QuizView #50
    @app.route('/quizzes', methods=['POST'])
    def questions_to_play():
        data = request.get_json()

        category_id = int(data['quiz_category']['id'])
        category = Category.query.get(category_id)
        previous_questions = data['previous_questions']

        try:
            #Get questions if category is not selected that have not been played; QuizView #105
            if category == None:
                get_questions = Question.query.filter(
                    Question.id.notin_(previous_questions)).all()

            #Get questions with selected category that have not been played
            else:
                get_questions = (Question.query.filter(
                    Question.category == category_id).filter(
                        Question.id.notin_(previous_questions)).all())

            questions = [question.format() for question in get_questions]

            #Randomize order of questions, deliver 1 at a time
            if (len(questions) == 0):
                quest = None
            else:
                quest = questions[random.randrange(
                    0, len(questions)
                )]  #rvu: can also use func.random() in your SQLAlchemy

            return jsonify({"question": quest, "success": True})

        except Exception as e:
            print("Exception >> ", e)
            print(sys.exc_info())
            abort(422)

    '''
  @TODO: DONE
  Create error handlers for all expected errors 
  including 404 and 422. 
  '''

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad request"
        }), 400

    @app.errorhandler(404)
    def resource_not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(500)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "internal server error"
        }), 500

    return app
    def setUp(self):
        """Difine test variables and initialize app."""
        self.app = create_app()
        self.client = self.app.test_client
        self.database_path = DATABASE_URL
        setup_db(self.app, self.database_path)

        # bind the app to the current context
        with self.app.app_context():
            self.db = db
            self.db.init_app(self.app)
            # create all tables
            self.db.create_all()

        # set up jwts
        self.user_headers = {
            'Authorization': 'Bearer {}'.format(os.environ['USER_JWT'])
        }
        self.extra_user_headers = {
            'Authorization': 'Bearer {}'.format(os.environ['USER2_JWT'])
        }
        self.staff_headers = {
            'Authorization': 'Bearer {}'.format(os.environ['STAFF_JWT'])
        }
        self.manager_headers = {
            'Authorization': 'Bearer {}'.format(os.environ['MANAGER_JWT'])
        }

        # set up initial clothes and users
        # using manager JWT and create clothes and users
        # ------------------------------
        # delete all existing clothes and users
        # ------------------------------
        res = self.client().get('/clothes', headers=self.manager_headers)
        data = json.loads(res.data)
        for clothes in data['clothes']:
            res = self.client().delete('/clothes/{}'.format(clothes['id']),
                                       headers=self.manager_headers)
        res = self.client().get('/users', headers=self.manager_headers)
        data = json.loads(res.data)
        for user in data['users']:
            res = self.client().delete('/users/{}'.format(user['id']),
                                       headers=self.manager_headers)

        # ------------------------------
        # create clothes
        # ------------------------------
        clothes = [{
            'type': 'shirt',
            'size': '100'
        }, {
            'type': 'pants',
            'size': '120'
        }]
        response = []
        for item_data in clothes:
            res = self.client().post('/clothes',
                                     json=item_data,
                                     headers=self.manager_headers)
            data = json.loads(res.data)
            response.append(data)

        # set clothes id for sequencing tests
        self.clothes_id = response[0]['clothes']['id']
        self.extra_clothes_id = response[1]['clothes']['id']

        # ------------------------------
        # create users
        # ------------------------------
        self.user_auth0_id = "google-oauth2|103606340396848658678"
        users = [{
            "e_mail": "*****@*****.**",
            "address": "Bunkyo-ku, Tokyo",
            "auth0_id": self.user_auth0_id,
            "role": "user"
        }, {
            "e_mail": "*****@*****.**",
            "address": "Shibuya-ku, Tokyo",
            "auth0_id": "auth0|5fdb49c07567970069085ee9",
            "role": "user"
        }]
        response = []
        for item_data in users:
            res = self.client().post('/users',
                                     json=item_data,
                                     headers=self.manager_headers)
            data = json.loads(res.data)
            response.append(data)
        staff = {
            "e_mail": "*****@*****.**",
            "address": "Shibuya-ku, Tokyo",
            "auth0_id": "auth0|5fadbe9e64abac00751e7c61",
            "role": "staff"
        }
        res = self.client().post('/users',
                                 json=staff,
                                 headers=self.manager_headers)
        manager = {
            "e_mail": "*****@*****.**",
            "address": "Shibuya-ku, Tokyo",
            "auth0_id": "auth0|5f6d247925dd140078ffbefc",
            "role": "manager"
        }
        res = self.client().post('/users',
                                 json=manager,
                                 headers=self.manager_headers)

        # set user ids for sequencing tests
        self.user_id = response[0]['user']['id']
        self.extra_user_id = response[1]['user']['id']

        # ------------------------------
        # make a reservation (with user JWT)
        # ------------------------------
        res = self.client().post(
            '/clothes/{}/reservations'.format(self.clothes_id),
            json={"auth0_id": "google-oauth2|103606340396848658678"},
            headers=self.user_headers)
        data = json.loads(res.data)

        # store reservation information for sequence tests
        self.reservation = {'clothes': data['clothes'], 'user': data['user']}
Example #29
0
def create_app(test_config=None):
  # create and configure the app
  app = Flask(__name__)
  setup_db(app)
  CORS(app)

  # CORS Headers 
  @app.after_request
  def after_request(response):
    response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization,true')
    response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
    return response

  
  @app.route('/books')
  def retrieve_books():
    selection = Book.query.order_by(Book.id).all()
    current_books = paginate_books(request, selection)

    if len(current_books) == 0:
      abort(404)

    return jsonify({
      'success': True,
      'books': current_books,
      'total_books': len(Book.query.all())
    })

  @app.route('/books/<int:book_id>', methods=['PATCH'])
  def update_book(book_id):

    body = request.get_json()

    try:
      book = Book.query.filter(Book.id == book_id).one_or_none()
      if book is None:
        abort(404)

      if 'rating' in body:
        book.rating = int(body.get('rating'))

      book.update()

      return jsonify({
        'success': True,
      })
      
    except:
      abort(400)

  @app.route('/books/<int:book_id>', methods=['DELETE'])
  def delete_book(book_id):
    try:
      book = Book.query.filter(Book.id == book_id).one_or_none()

      if book is None:
        abort(404)

      book.delete()
      selection = Book.query.order_by(Book.id).all()
      current_books = paginate_books(request, selection)

      return jsonify({
        'success': True,
        'deleted': book_id,
        'books': current_books,
        'total_books': len(Book.query.all())
      })

    except:
      abort(422)

  @app.route('/books', methods=['POST'])
  def create_book():
    body = request.get_json()

    new_title = body.get('title', None)
    new_author = body.get('author', None)
    new_rating = body.get('rating', None)

    try:
      book = Book(title=new_title, author=new_author, rating=new_rating)
      book.insert()

      selection = Book.query.order_by(Book.id).all()
      current_books = paginate_books(request, selection)

      return jsonify({
        'success': True,
        'created': book.id,
        'books': current_books,
        'total_books': len(Book.query.all())
      })

    except:
      abort(422)

  # @TODO: Review the above code for route handlers. 
  #        Pay special attention to the status codes used in the aborts since those are relevant for this task! 

  # @TODO: Write error handler decorators to handle AT LEAST status codes 400, 404, and 422. 
    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "Resource not found"
        }), 404

    
    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "Bad Request"
        }), 400

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(405)
    def not_allowed(error):
        return jsonify({
            "success": False,
            "error": 405,
            "message": "method not allowed"
        }), 405


  return app

    
Example #30
0
def create_app(test_config=None):
    
    app = Flask(__name__)
    setup_db(app)
    CORS(app,  resources={'/': {'origins': '*'}})


    @app.route("/")
    def home():
        hiText = "Hi ! I`m Shruti"
        return str(hiText)


    @app.route("/actors", methods=["GET"])
    @requires_auth('get:actors')
    def get_actors(token):
        try:
            actors = Actor.query.all()
            return jsonify({"success": True, "actors": [d.format() for d in actors]}), 200
        except:
            abort(404)


    @app.route("/movies", methods=["GET"])
    @requires_auth('get:movies')
    def get_movies(token):
        try:
            movies = Movie.query.all()
            return jsonify({"success": True, "movies": [d.format() for d in movies]}), 200
        except:
            abort(404)


    @app.route("/actors/create", methods=["POST"])
    @requires_auth('post:actors')
    def create_actor(token):
        try:
            req = request.get_json()
            act = Actor(name=req['name'], gender=req['gender'], age=req['age'])
            act.insert()
            actors = Actor.query.all()
            return jsonify({"success": True, "actors": [d.format() for d in actors]}), 200
        except:
            abort(404)


    @app.route("/movies/create", methods=["POST"])
    @requires_auth('post:movies')
    def create_movie(token):
        try:
            req = request.get_json()
            mov = Movie(title=req['title'], release_date=req['release_date'])
            mov.insert()
            movies = Movie.query.all()
            return jsonify({"success": True, "movies": [d.format() for d in movies]}), 200
        except:
            abort(404)


    @app.route("/actors/<int:id>", methods=["DELETE"])
    @requires_auth('delete:actor')
    def delete_actor(payload, id):
        try:
            actor = Actor.query.filter(Actor.id == id).one_or_none()
            if actor is None:
                abort(404)
            else:
                actor.delete()
                actors = Actor.query.all()
                return jsonify({"success": True, "actors": [d.format() for d in actors]}), 200
        except:
            abort(404)


    @app.route("/movies/<int:id>", methods=["DELETE"])
    @requires_auth('delete:movie')
    def delete_movie(payload, id):
        try:
            movie = Movie.query.filter(Movie.id == id).one_or_none()
            if movie is None:
                abort(404)
            else:
                movie.delete()
                movies = Movie.query.all()
                return jsonify({"success": True, "movies": [d.format() for d in movies]}), 200
        except:
            abort(404)


    @app.route("/actors/<int:id>", methods=["PATCH"])
    @requires_auth('patch:actor')
    def patch_actor(payload, id):
        try:
            actor = Actor.query.filter(Actor.id == id).one_or_none()
            req = request.get_json()
            if('name' in req):
                actor.name = req['name']
            if('gender' in req):
                actor.gender = req['gender']
            if('age' in req):
                actor.age = req['age']
            actor.update()
            actors = Actor.query.all()
            return jsonify({"success": True, "actors": [d.format() for d in actors]}), 200
        except:
            abort(404)


    @app.route("/movies/<int:id>", methods=["PATCH"])
    @requires_auth('patch:movie')
    def patch_movie(payload, id):
        try:
            movie = Movie.query.filter(Movie.id == id).one_or_none()
            req = request.get_json()
            if('title' in req):
                movie.title = req['title']
            if('release_date' in req):
                movie.release_date = req['release_date']
            movie.update()
            movies = Movie.query.all()
            return jsonify({"success": True, "movies": [d.format() for d in movies]}), 200
        except:
            abort(404)


    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resourse not found"
        }), 404


    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422


    @app.errorhandler(405)
    def method_not_allowed(error):
        return jsonify({
            'code': 405,
            'success': False,
            'message': 'method not allowed'
        }), 405


    @app.errorhandler(500)
    def internal_server_error(error):
        return jsonify({
            'code': 500,
            'success': False,
            'message': 'server error'
        }), 500


    @app.errorhandler(AuthError)
    def internal_auth_error(error):
        return jsonify({
            'error': error.error,
            'success': False,
            'message': error.status_code
        }), error.status_code
    
    return app
Example #31
0
def create_app(test_config=None):
    '''
  Create and configure the app.
  '''
    app = Flask(__name__, instance_relative_config=True)
    setup_db(app)
    '''
  Format the categories to fit JS needs.
  '''
    categories_query = Category.query.all()
    categories = {}
    for category in categories_query:
        cat = {}
        cat[category.id] = category.type
        categories.update(cat)
    '''
  @TODO: Set up CORS. Allow '*' for origins. Delete the sample route after completing the TODOs
  Sorry, I don't know how to let 'cors' work.
  '''
    #cors = CORS(app, resources={r"*/api/*": {"origins": "*"}})

    @app.after_request
    def after_request(response):
        '''
    Use the after_request decorator to set Access-Control-Allow
    '''
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type, Authorization, True')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET, POST, PATCH, DELETE, OPTIONS')
        return response

    @app.route('/categories', methods=['GET'])
    def get_categories():
        '''
    Handle GET requests for all available categories.
    '''
        categories = Category.query.all()

        if len(categories) == 0:
            abort(404)

        formatted_categories = [category.format() for category in categories]

        return jsonify({'success': True, 'categories': formatted_categories})

    @app.route('/questions', methods=['GET', 'POST'])
    def get_search_qustions():
        '''
    If the request.method is POST, then get questions based on a search term. 
    Return any questions for whom the search term is a substring of the question. 
    
    And if the request.method is GET, then get all questions in database, 
    including pagination (every 10 questions). 
 
    PROBLEM!
    The pagination is not visable although the curl test is right. 
    Please help. Thanks a lot!
    '''
        if request.method == 'POST':
            body = request.get_json()

            if 'searchTerm' in body:
                search_item = '%' + body['searchTerm'] + '%'
                selection = Question.query.order_by(Question.id).filter(
                    Question.question.ilike(search_item)).all()
                current_questions = paginate_questions(request, selection)

            else:
                abort(404)

        else:
            selection = Question.query.order_by(Question.id).all()
            current_questions = paginate_questions(request, selection)

        return jsonify({
            'success': True,
            'questions': current_questions,
            'totalQuestions': len(selection),
            'categories': categories
        })

    @app.route('/questions/<int:question_id>', methods=['DELETE'])
    def delete_question(question_id):
        '''
    DELETE question using a question ID. 

    TESTED: When click the trash icon next to a question, the question will be removed.
    This removal will persist in the database and when you refresh the page. 
    '''
        question = Question.query.filter(
            Question.id == question_id).one_or_none()

        if question == None:
            abort(404)

        else:
            question.delete()

            return jsonify({
                'success': True,
                'deleted': question_id,
                'totalQuestions': len(Question.query.all()),
            })

    @app.route('/add', methods=['POST'])
    def create_new_question():
        '''
    POST a new question which requires the question and answer text, 
    category, and difficulty score.

    TESTED: When you submit a question on the "Add" tab, 
    the form will clear and the question will appear at the end of the last page
    of the questions list in the "List" tab.  
    '''
        body = request.get_json()

        if body.get('question') == '' or body.get('answer') == '':
            abort(422)

        new_question = body.get('question', None)
        new_answer = body.get('answer', None)
        new_category = int(body.get('category', None)) + 1
        new_diffidulty = body.get('difficulty', None)

        try:
            question = Question(question=new_question,
                                answer=new_answer,
                                category=new_category,
                                difficulty=new_diffidulty)
            question.insert()

            selection = Question.query.order_by(Question.id).all()
            current_questions = paginate_questions(request, selection)

            return jsonify({
                'success': True,
                'created': question.id,
                'questions': current_questions,
                'total_questions': len(Question.query.all())
            })

        except:
            abort(422)

    @app.route('/categories/<int:category_id>', methods=['GET'])
    def get_category_qustions(category_id):
        '''
    Get questions based on category. 

    TESTED: In the "List" tab / main screen, clicking on one of the 
    categories in the left column will cause only questions of that 
    category to be shown. 
    '''
        page = request.args.get('page', 1, type=int)
        selection = Question.query.filter(
            Question.category == category_id).order_by(Question.id).all()
        current_questions = paginate_questions(request, selection)

        return jsonify({
            'success': True,
            'questions': current_questions,
            'page': page,
            'totalQuestions': len(selection),
            'currentCategory': category_id,
        })

    @app.route('/play', methods=['GET'])
    def choose_category():
        '''
    GET requests for all available categories.     

    TEST: In the "Play" tab, display categories, after a user selects "All" or a category,
    turn to question_quiz form.
    '''
        return jsonify({'success': True, 'categories': categories})

    @app.route('/play/getnextquestion', methods=['POST'])
    def get_next_question():
        '''
    Display a random question within the given category, 
    if provided, and that is not one of the previous questions. 

    TESTED:One question at a time is displayed, the user is allowed to answer
    and shown whether they were correct or not. 
    '''
        body = request.get_json()
        previous_questions = body.get('previous_questions', None)
        get_category_id = body.get('quiz_category', None).get('id', None)

        category_id = int(get_category_id)

        if category_id == 0:
            questions = Question.query.filter(
                ~Question.id.in_(previous_questions)).all()

        else:
            questions = Question.query.filter(
                Question.category == category_id,
                ~Question.id.in_(previous_questions)).all()

        formatted_questions = [question.format() for question in questions]
        total_remained_questions = len(formatted_questions)

        if total_remained_questions != 0:
            random_num = random.randint(0, total_remained_questions - 1)
            question = formatted_questions[random_num]

        else:
            question = None

        return jsonify({
            'success': True,
            'question': question,
        })

    @app.errorhandler(400)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad request"
        }), 400

    @app.errorhandler(404)
    def resource_not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(405)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 405,
            "message": "method not allowed"
        }), 405

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(500)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "internal server error"
        }), 500

    return app
Example #32
0
        size=company_data.get('size'),
        remote=company_data.get('allows_remote')
    )
    company.techs = [Tech(name=tech_name) for tech_name in company_data.get('stack', [])]

    company.location = Location(
        city=company_data['location'].get('city'),
        country=company_data['location'].get('country'),
        postcode=company_data['location'].get('postcode')
    )

    session.add(company)
    session.commit()


if __name__ == "__main__":
    db_url = 'postgresql://*****:*****@localhost/ourstack'
    companies_path = '../companies'

    # allows specifying the db url when calling the script directly
    if len(sys.argv) > 1:
        db_url = sys.argv[1]

    session = setup_db(db_url)

    for company_data in parse_directory(companies_path):
        load_company(session, company_data)

    for instance in session.query(Company):
        print(instance.name)
Example #33
0
def create_app(test_config=None):
    app = Flask(__name__)
    setup_db(app)
    db_drop_and_create_all()

    CORS(app)

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PATCH,POST,DELETE,OPTIONS')
        return response

    def paginate_results(request, selection):
        page = request.args.get('page', 1, type=int)

        start = (page - 1) * ROWS_PER_PAGE
        end = start + ROWS_PER_PAGE

        objects = [object.format for object in selection]
        return objects[start:end]

    #----------------------------------------------------------------------------#
    # Endpoint /actors GET/POST/DELETE/PATCH
    #----------------------------------------------------------------------------#

    @app.route('/actors')
    @requires_auth('read:actors')
    def get_actors(payload):
        actors = Actor.query.all()
        actors_paginated = paginate_results(request, actors)

        if len(actors_paginated) == 0:
            abort(404)

        return jsonify({'success': True, 'actors': actors_paginated})

    @app.route('/actors', methods=['POST'])
    @requires_auth('create:actors')
    def insert_actors(payload):
        body = request.get_json()

        if not body:
            abort(400)

        name = body.get('name', None)
        age = body.get('age', None)

        gender = body.get('gender', 'Other')

        if not name or not age:
            abort(422)

        new_actor = (Actor(name=name, age=age, gender=gender))
        new_actor.insert()

        return jsonify({'success': True, 'created': new_actor.id})

    @app.route('/actors/<actor_id>', methods=['PATCH'])
    @requires_auth('edit:actors')
    def edit_actors(payload, actor_id):
        body = request.get_json()

        if not actor_id or not body:
            abort(400)

        actor_to_update = Actor.query.filter(
            Actor.id == actor_id).one_or_none()

        if not actor_to_update:
            abort(404)

        name = body.get('name', actor_to_update.name)
        age = body.get('age', actor_to_update.age)
        gender = body.get('gender', actor_to_update.gender)

        actor_to_update.name = name
        actor_to_update.age = age
        actor_to_update.gender = gender

        actor_to_update.update()

        return jsonify({
            'success': True,
            'updated': actor_to_update.id,
            'actor': [actor_to_update.format]
        })

    @app.route('/actors/<actor_id>', methods=['DELETE'])
    @requires_auth('delete:actors')
    def delete_actors(payload, actor_id):
        if not actor_id:
            abort(400)

        actor_to_delete = Actor.query.filter(
            Actor.id == actor_id).one_or_none()

        if not actor_to_delete:
            abort(404)

        actor_to_delete.delete()

        return jsonify({'success': True, 'deleted': actor_id})

    #----------------------------------------------------------------------------#
    # Endpoint /movies GET/POST/DELETE/PATCH
    #----------------------------------------------------------------------------#

    @app.route('/movies', methods=['GET'])
    @requires_auth('read:movies')
    def get_movies(payload):
        movies = Movie.query.all()
        movies_paginated = paginate_results(request, movies)

        if len(movies_paginated) == 0:
            abort(404)

        return jsonify({'success': True, 'movies': movies_paginated})

    @app.route('/movies', methods=['POST'])
    @requires_auth('create:movies')
    def insert_movies(payload):
        body = request.get_json()

        if not body:
            abort(400)

        title = body.get('title', None)
        release_date = body.get('release_date', None)

        if not title or not release_date:
            abort(422)

        new_movie = (Movie(title=title, release_date=release_date))
        new_movie.insert()

        return jsonify({'success': True, 'created': new_movie.id})

    @app.route('/movies/<movie_id>', methods=['PATCH'])
    @requires_auth('edit:movies')
    def edit_movies(payload, movie_id):
        body = request.get_json()

        if not movie_id or not body:
            abort(400)

        movie_to_update = Movie.query.filter(
            Movie.id == movie_id).one_or_none()

        if not movie_to_update:
            abort(404)

        title = body.get('title', movie_to_update.title)
        release_date = body.get('release_date', movie_to_update.release_date)

        movie_to_update.title = title
        movie_to_update.release_date = release_date

        movie_to_update.update()

        return jsonify({
            'success': True,
            'edited': movie_to_update.id,
            'movie': [movie_to_update.format]
        })

    @app.route('/movies/<movie_id>', methods=['DELETE'])
    @requires_auth('delete:movies')
    def delete_movies(payload, movie_id):
        if not movie_id:
            abort(400)

        movie_to_delete = Movie.query.filter(
            Movie.id == movie_id).one_or_none()

        if not movie_to_delete:
            abort(404)

        movie_to_delete.delete()

        return jsonify({'success': True, 'deleted': movie_id})

    #----------------------------------------------------------------------------#
    # Error Handlers
    #----------------------------------------------------------------------------#
    @app.errorhandler(500)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "Internal server error"
        }), 500

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "Unprocessable entity"
        }), 422

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "Bad request"
        }), 400

    @app.errorhandler(404)
    def ressource_not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "Not found"
        }), 404

    @app.errorhandler(AuthError)
    def authentification_failed(AuthError):
        return jsonify({
            "success": False,
            "error": AuthError.status_code,
            "message": AuthError.error['description']
        }), AuthError.status_code

    return app
Example #34
0
File: init_db.py Project: cjgu/todo
def main():
    models.setup_db()
    models.reset_db()
Example #35
0
def upsert_content():
    from models import setup_db
    setup_db()