ASK-ANSWER is an application where student get to ask question and their tutor get to answer it. The app API is built around a RESTful concepts and it performs all CRUD operations. It is an app I am building to practice my Full Stack development skills.
The App does the following by the help of the built API,
- Create question
- Answer a question
- Delete question
- Answer question
The application make us of Google authenticator to verify users.
All backend code follows PEP8 style guidelines.
├── README.md
├── frontend
│  ├── public
│  ├── src
│  ├── package.json
└── backend
├── app.py
├── models.py # Houses all the models
├── requirements.txt # The dependencies we need to install with `pip3 install -r requirements.txt`
└── config.psql
Overall:
- Models are located in
models.py
file - Controllers are located in
app.py
file - COnfigurations are located in
config.py
file
The prerequites tools for local development are:
- Python
- Pip
- Node
- virtualenv: To create an isolated Python environment
- Postgres
It is a good practice to keep your app dependencies isolated by working a virtual environment.
- To Initialize a virtual enviroment, run
python -m virtualenv env
- To Activate the environment run
source env/bin/activate
Note - In Windows, the env
does not have a bin
directory. Therefore, you'd use the analogous command shown below:
source env/Scripts/activate
To run the backend application, you need to install the required packages by doing the following,
- navigate into the backend folder
- run
pip install -r requirements.txt
After succesfull installation of the packages, you can get the app running by running the following commands
export FLASK_APP=myapp
export FLASK_DEBUG=True # enables debug mode
flask run
Note: For window, change export to set i.e. set FLASK_APP=myapp
The application is run on http://127.0.0.1:5000/
by default and is a proxy in the frontend configuration.
With Postgres running, create a database using the command below,
createbd altschool
Create the database tables by running
flask db init # Initialize flask migrate script
flask db migrate # Create the tables
flask db upgrade
# To add the changes to the database
flask db downgrade
# To roll back the changes from the database
The app is built with React so there is need to install the frontend dependencies using Node.js and NPM
You can confirm if Node.js and NPM is installed successfully using the codes below
node -v
npm -v
From the frontend folder, run the following commands to start the client:
npm install # run this once to install dependencies
npm start
By default, the frontend will run on localhost:3000
.
This application is not deployed and can only be run locally. The backend application is hosted at the default port (Base URL) which is set as a proxy in the frontend application.
- Base URL: http://127.0.0.1:5000/
- Authentication: This application doesn't require authentication or API keys.
- Errors format: All errors are returned as a JSON object as shown below
{
'success': False,
'error': 404,
'message': "Resources not found"
}
-
Error Codes and Messages: The API will return one out of four(4) error type whenever the request fail:
- 400: Bad request
- 404: Resources not found
- 405: Methods not allowed
- 422: Request unprocessable
-
Error Mesaages possible solution:
- Bad Request: Check the format of your request. Make sure your format satisfies what the endpoint and the endpoint method requires.
- Resources not found: Search for resources that exist in the database or server
- Methods not allowed: Check if the method is allowed for the particular endpoint
- Request unprocessable: Try again! Server error.
- General:
- This endpoint fetches all unanswered questions question
- Fetched results is an object with
questions
,total_questions
, andanswered_questions
keys. - Request argument: None
- Sample:
- Without argument:
curl http://127.0.0.1:5000/<track>/all_questions
- Without argument:
- Response: Json
{
"answered_questions": 1,
"questions": [
{
"description": "How do I select an Html element",
"id": 3,
"images": [],
"title": "Js"
},
{
"description": "What is the selector for class",
"id": 2,
"images": [],
"title": "Css"
},
{
"description": "is <a> an inline or block element.",
"id": 1,
"images": [],
"title": "Html"
}
],
"total_questions": 3
}
-
General:
- This endpoint create a question
- Fetched results is an object with
questions
,total_questions
, andanswered_questions
keys. - Request argument: None
-
Sample:
- Without argument:
curl http://127.0.0.1:5000/<track>/add_question -H "Content-Type: application/json" -d '{"title": "Invalid commands", "question": "I am having an error when I run npm run"}'
- Without argument:
-
Request: Json
{
"title": "Invalid commands",
"question": "I am having an error when I run npm run",
"images": [] # This is optional
}
- Response: Json
{
"success": true
}
- General:
- This endpoint fetches an unanswered question based on the given question id
- Fetched results is an object with
question
key. - Request argument: None
- Sample:
- Without argument:
curl http://127.0.0.1:5000/<track>/all_questions/1
- Without argument:
- Response: Json
{
"question": {
"description": "is <a> an inline or block element.",
"id": 1,
"images": [],
"title": "Html"
}
}
- General:
- This endpoint modified the answered column of a question from false to true i.e., a question has been answered
- Fetched results is an object with
questions
,total_questions
, andanswered_questions
keys. - Request argument: None
- Sample:
- Without argument:
curl http://127.0.0.1:5000/<track>/all_questions/1
- Without argument:
- Response: Json
{
"answered_questions": 2,
"questions": [
{
"description": "I am having an error when I run npm run",
"id": 5,
"images": [],
"title": "Invalid commands"
},
{
"description": "How do I select an Html element",
"id": 3,
"images": [],
"title": "Js"
},
{
"description": "What is the selector for class",
"id": 2,
"images": [],
"title": "Css"
}
],
"total_questions": 3
}
- General:
- This endpoint fetches all the answered questions
- Fetched results is an object with
questions
, andtotal_questions
keys. - Request argument: None
- Sample:
- Without argument:
curl http://127.0.0.1:5000/<track>/answered_questions
- Without argument:
- Response: Json
{
"questions": [
{
"description": "How do I start a React app",
"id": 4,
"images": [],
"title": "React"
},
{
"description": "is <a> an inline or block element.",
"id": 1,
"images": [],
"title": "Html"
}
],
"total_questions": 2
}
- General:
- This endpoint fetches an answered question based on the given id
- Fetched results is an object with
question
key. - Request argument: None
- Sample:
- Without argument:
curl http://127.0.0.1:5000/<track>/answered_questions/1
- Without argument:
- Response: Json
{
"question": {
"description": "is <a> an inline or block element.",
"id": 1,
"images": [],
"title": "Html"
}
}
-
General:
- This endpoint filter questions based on the given title and it is case insensitive.
- Fetched results is an object with
questions
,total_questions
, andanswered_questions
keys. - Request argument: None
-
Sample:
- Without argument:
curl http://127.0.0.1:5000/<track>/all_question -H "Content-Type: application/json" -d '{"title": "Invalid commands", "offset": 0, "limit: 3}'
- Without argument:
-
Request: Json
{
"title": "Invalid",
"offset": 0,
"limit": 3
}
- Response: Json
{
"answered_questions": 0,
"questions": [
{
"description": "I am having an error when I run npm run",
"id": 5,
"images": [],
"title": "Invalid commands"
}
],
"total_questions": 1
}
-
General:
- This endpoint deletes a question of the given question_id if it exists
- Returned results is an object with with
questions
,total_questions
, andanswered_questions
.
-
Sample:
- Without argument:
curl -X DELETE http://127.0.0.1:5000/frontend/all_questions/1
- Without argument:
-
Response: json
{
"answered_questions": 1,
"questions": [
{
"description": "I am having an error when I run npm run",
"id": 5,
"images": [],
"title": "Invalid commands"
},
{
"description": "How do I select an Html element",
"id": 3,
"images": [],
"title": "Js"
},
{
"description": "What is the selector for class",
"id": 2,
"images": [],
"title": "Css"
}
],
"total_questions": 3
}
-
General:
- This endpoint create comment for a given question
- Request argument: None
-
Sample:
- Without argument:
curl http://127.0.0.1:5000/<track>/all_question/2/comments -H "Content-Type: application/json" -d '{"name": "Joel", "answer": "The selector for class is '.' without the quote"}'
- Without argument:
-
Request: Json
{
"name": "Joel",
"answer": "The selector for class is '.' without the quote"
}
- Response: Json
{
"success": true
}
- General:
- This endpoint fetches all comments of a given id.
- Fetched results is an object with
comments
andtotal_comments
keys. - Request argument: None
- Sample:
- Without argument:
curl http://127.0.0.1:5000/<track>/answered_questions/2/comments
- Without argument:
- Response: Json
{
"comments": [
{
"answer": "The selector for class is '.' without the quote",
"date": "Thu, 13 Oct 2022 13:30:03 GMT",
"id": 4,
"name": "Joel",
"question_id": 2
}
],
"total_comments": 1
}
The app is not deployed
Joel Ojerinde
Udacity and AltSchool Africa