Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/2 implement endpoint #41

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions backend/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import os
from flaskr import create_app

os.environ['FLASK_APP'] = 'flaskr:create_app'
os.environ['FLASK_ENV'] = 'development'

app = create_app()

if __name__ == '__main__':
app.run()
157 changes: 155 additions & 2 deletions backend/flaskr/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import os
from flask import Flask, request, abort, jsonify
from flask import Flask, request, abort, jsonify, Response
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
import random
from sqlalchemy import delete

from models import setup_db, Question, Category
from models import db, setup_db, Question, Category

QUESTIONS_PER_PAGE = 10

Expand All @@ -21,17 +22,38 @@ def create_app(test_config=None):
"""
@TODO: Set up CORS. Allow '*' for origins. Delete the sample route after completing the TODOs
"""
#CORS(app, resources={r"*/api/*" : {origins: '*'}})

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, PATCH, DELETE, OPTIONS')
return response

"""
@TODO:
Create an endpoint to handle GET requests
for all available categories.
"""
@app.route('/categories')
def get_categories():
# Implement pagination
page = request.args.get('page', 1, type=int)
start = (page - 1) * 10
end = start + 10

categories = get_all_formatted_category()

return jsonify({
'success': True,
'categories': categories[start:end],
'total_categories': len(categories)
})

"""
@TODO:
Expand All @@ -45,6 +67,24 @@ def create_app(test_config=None):
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():
# Implement pagination
page = request.args.get('page', 1, type=int)
start = (page - 1) * 10
end = start + 10

categories = get_all_formatted_category()

questions = Question.query.all()
formatted_questions = [question.format() for question in questions]

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

"""
@TODO:
Expand All @@ -53,6 +93,32 @@ def create_app(test_config=None):
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):
id_question = int(id)

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

if question is None:
handle_error(404, 'Error: question not found')

db.session.delete(question)
db.session.commit()
except:
handle_error(422, 'An error occurred!')

return jsonify({
'success': True,
'message': "deleted successfully"
})

# return jsonify({
# 'success': True,
# 'deleted': id_question,
# 'question': current_questions,
# 'total_question': len(current_questions)
# })

"""
@TODO:
Expand All @@ -64,6 +130,24 @@ def create_app(test_config=None):
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()
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, category=int(new_category), difficulty=int(new_difficulty))
question.insert()
except:
handle_error(422, 'An error occurred!')

return({
'success': True,
'message': 'Create successfully!'
})

"""
@TODO:
Expand All @@ -75,6 +159,22 @@ def create_app(test_config=None):
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():
page = request.args.get('page', 1, type=int)
start = (page - 1) * 10
end = start + 10

body = request.get_json()
key_word = body['searchTerm']
questions = db.session.query(Question).filter(Question.question.ilike(f'%{key_word}%')).all()
formatted_questions = [question.format() for question in questions]

return jsonify({
'success': True,
'questions': formatted_questions[start:end],
'total_questions': len(formatted_questions),
})

"""
@TODO:
Expand All @@ -84,6 +184,25 @@ def create_app(test_config=None):
categories in the left column will cause only questions of that
category to be shown.
"""
@app.route("/categories/<int:id>/questions")
def get_all_question(id):
# Implement pagination
page = request.args.get('page', 1, type=int)
start = (page - 1) * 10
end = start + 10

id_category = int(id)
categories = Category.query.filter_by(id=id_category).all()
formatted_categories = [category.format() for category in categories]
questions = Question.query.filter_by(category=id_category).all()
formatted_questions = [question.format() for question in questions]

return jsonify({
'success': True,
'questions': formatted_questions[start:end],
'total_questions': len(formatted_questions),
'currentCategory': formatted_categories[0]
})

"""
@TODO:
Expand All @@ -96,12 +215,46 @@ def create_app(test_config=None):
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_question_to_play():
data = request.get_json()
previous_questions = data.get('previous_questions')
quiz_category = data.get('quiz_category')
result = None
questions = []

# get all questions
if quiz_category['id'] is 0:
questions = Question.query.all()
else:
questions = Question.query.filter_by(category=quiz_category['id']).all()

format_questions = [question.format() for question in questions]
if len(format_questions) != 0:
if len(previous_questions) is 0:
result = format_questions[0]
else:
data = [question for question in format_questions if question['id'] not in previous_questions]
if len(data) != 0:
result = data[0]

return jsonify({
'question': result
})

"""
@TODO:
Create error handlers for all expected errors
including 404 and 422.
"""
def handle_error(code, message):
error_message = ({'message': message})
abort(Response(error_message, code))

def get_all_formatted_category():
categories = Category.query.all()
formatted_categories = [category.format() for category in categories]
return formatted_categories

return app

5 changes: 3 additions & 2 deletions backend/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import json

database_name = 'trivia'
database_path = 'postgresql://{}/{}'.format('localhost:5432', database_name)
database_path = 'postgresql://postgres:12345@{}/{}'.format('localhost:5432', database_name)

db = SQLAlchemy()

Expand All @@ -17,7 +17,8 @@ def setup_db(app, database_path=database_path):
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.app = app
db.init_app(app)
db.create_all()
with app.app_context():
db.create_all()

"""
Question
Expand Down
Loading
Loading