An implementation of a beer manager application for keeping track of beers, users, beer reviews, and user favorites. The implementation is using Flask, flask-restful, and deployed to the Google App Engine. Flask micro framework.
-
Install the App Engine Python SDK. See the README file for directions. You'll need python 2.7 and pip 1.4 or later installed too.
-
Clone this repo with
git clone https://github.com/pwojt/beer_app_414.git
-
Install dependencies in the project's lib directory. Note: App Engine can only import libraries from inside your project directory.
pip install -r requirements.txt -t lib
-
Run this project locally from the command line:
dev_appserver.py .
Visit the application http://localhost:8080
To deploy the application:
-
Use the Admin Console to create a project/app id. (App id and project id are identical)
-
appcfg.py -A <your-project-id> --oauth2 update .
-
Congratulations! Your application is now live at your-app-id.appspot.com
-
Command format:
/api/v1.0/<object>[/id[/sub_object]]
object - specifies the object you want to act on (beers, beer_glasses, beer_reviews, users, favorites)
id - (optional) the object ID you want to act on
sub_object - (optional) if ID is specified, gets the sub object, ie all user reviews would be:
/api/v1.0/user/<id>/reviews
-
Authentication:
The api supports basic authentication using user name and password.
When the application first runs, it creates a default admin user to allow access to the system.
Default admin credentials:
user_name: admin
password: beer_app1
-
Sorting:
To sort lists returned from get specify the sort parameter via url arguments.
sort=[field name] - (optional) sort on specified field name, returns 400 result if sort field is not available
order=[asc|desc] - (optional) if sort is selected, order descending or ascending (default) sort order
-
Return:
All data is returned as a JSON object.
Each object returns the uri reference back to the object
When posting or putting an object, a single entry with the object put is returned
When getting an object, the single object is returned
{ "beer": { <beer object> } }
When getting multiple object an array of the object is returned
{ "beers": [<beer object>`1, ... <beer object>`n] }
When deleting an object, the object is returned along with the action: deleted.
-
Errors:
400 - Bad Input
404 - Object not found
405 - Not allowed
429 - Rate limit exceeded (includes allowed_in seconds when action is allowed next)
-
Supported Input:
The API supports a variety of input including JSON, form, url args, and anything that can be parsed from the request as long as the variable name matches the input name
The method of input is supported via almost all commands, commands that have multiple ways to post are get are documented below
beer input:
{
'name': string, [Required, unique]
'description': string, [Required]
'ibu': float,
'calories': float,
'abv': float,
'style': float,
'brewery_location': float,
'beer_glass_id': int,
}
beer object:
{
'name': fields.String,
'description': fields.String,
'ibu': fields.Float,
'calories': fields.Float,
'abv': fields.Float,
'style': fields.String,
'brewery_location': fields.String,
'beer_glass': ReferenceUrlField('beer_glass', absolute=True),
'uri': IdUrlField('beer', absolute=True),
}
- Get list of beers:
Input: None Output: beers array
/api/v1.0/beers - GET
- Get specific beer:
Input: Beer ID Output: beer object
/api/v1.0/beers/<id> - GET
- Add new beer:
Input: Required fields passed in with request Output: beer object or error
/api/v1.0/beers - POST
- Update beer:
Input: Beer ID, Fields that need to be updated Output: updated beer object or error
/api/v1.0/beers/<id> - PUT
- Delete beer:
Input: Beer ID Output: deleted beer object and action or error
/api/v1.0/beers/<id> - DELETE
user input:
{
'user_name': string, [Required]
'first_name': string, [Required]
'last_name': string, [Required]
'password': string [Required]
}
user object:
{
'user_name': fields.String,
'first_name': fields.String,
'last_name': fields.String,
'last_beer_add_date': fields.DateTime,
'uri': IdUrlField('user', absolute=True),
}
- Get list of users:
Input: None Output: user array
/api/v1.0/users - GET
- Get specific user:
Input: User ID Output: user object
/api/v1.0/users/<id> - GET
- Add new user:
Input: Required fields passed in with request Output: user object or error
/api/v1.0/user - POST
- Update user:
Input: User ID, Fields that need to be updated Output: updated user object or error
/api/v1.0/users/<id> - PUT
- Delete user:
Input: User ID Output: deleted user object and action or error
/api/v1.0/users/<id> - DELETE
beer_glass input:
{
'name': fields.String, [Required]
'description': fields.String,
'capacity': fields.Float,
}
beer_glass object:
{
'name': fields.String,
'description': fields.String,
'capacity': fields.Float,
'uri': IdUrlField('beer_glass', absolute=True),
}
- Get list of beer glasses:
Input: None Output: beer_glass array
/api/v1.0/beer_glasses - GET
- Get specific beer glass:
Input: Beer Glass ID Output: beer_glass object
/api/v1.0/beer_glasses/<id> - GET
- Add new beer glass:
Input: Required fields passed in with request Output: beer_glass object or error
/api/v1.0/beer_glasses - POST
- Update beer glass:
Input: Beer Glass ID, Fields that need to be updated Output: updated beer_glass object or error
/api/v1.0/beer_glasses/<id> - PUT
- Delete beer glass:
Input: Beer Glass ID Output: deleted beer_glass object and action or error
/api/v1.0/beer_glasses/<id> - DELETE
beer_review input
{
'beer_id': int, [Required]
'aroma': float, [Required]
'appearance': float, [Required]
'taste': float, [Required]
'palate': float, [Required]
'bottle_style': float, [Required]
'comments': fields.String,
}
beer_review object
{
'user': fields.Nested(user_reference_fields), [Required]
'beer': fields.Nested(beer_reference_fields), [Required]
'date_created': fields.DateTime, [auto generated]
'aroma': fields.Float, [Required]
'appearance': fields.Float, [Required]
'taste': fields.Float, [Required]
'palate': fields.Float, [Required]
'bottle_style': fields.Float, [Required]
'overall': fields.Float, [output - calculated]
'comments': fields.String,
'uri': IdUrlField('review', absolute=True)
}
beer_review_summary object
{
'count': fields.Integer,
'aroma': fields.Float,
'appearance': fields.Float,
'taste': fields.Float,
'palate': fields.Float,
'bottle_style': fields.Float,
'overall': fields.Float,
'comments': fields.String,
'beer': fields.Nested(beer_reference_fields),
}
To get summaries of reviews use type argument to specify summary
IE:
/api/v1.0/beer_reviews?type=summary
- Get all beer reviews:
Input: None Output: beer_review array or beer_review_summary array
/api/v1.0/beer_reviews - GET
- Get specific beer review:
Input: Beer Review ID Output: beer_review object
/api/v1.0/beer_reviews/<id> - GET
- Get beer review for a beer:
Input: Beer ID Output: beer_review array or beer_review_summary object
/api/v1.0/beers/<id>/reviews - GET
- Get reviews for specific user:
Input: Beer ID Output: beer_review array
/api/v1.0/users/<id>/reviews - GET
- Add beer review:
/api/v1.0/beer_reviews - POST
Input: Beer ID and beer_review input object Output: beer_review object/api/v1.0/beers/<id>/reviews - POST
favorites input
{
'beer_id': int, [Required]
}
favorites object
{
'beer': fields.Nested(beer_summary_fields),
'user': fields.Nested(user_summary_fields),
'uri': IdUrlField('favorite', absolute=True),
}
- Get all favorites for logged in user:
Input: None Output: favorites array
/api/v1.0/favorites - GET
- Get specific favorite:
Input: Favorite ID Output: favorite object
/api/v1.0/favorites/<id> - Get
- Get favorites for a user:
Input: User ID Output: favorite array
/api/v1.0/users/<user id>/favorites - GET
- Get favorites for a beer:
Input: None Output: favorites array
/api/v1.0/beers/<beer id>/favorites - GET
- Add favorite beer for logged in user:
/api/v1.0/favorites - POST
Input: Beer ID Output: favorite object/api/v1.0/beers/<beer id>/favorites - POST
- Delete favorite by id:
Input: Favorite ID Output: deleted favorite object and action: deleted
/api/v1.0/favorites/<id> - DELETE
- Delete favorite beer for logged in user:
Input: Beer ID Output: deleted favorite object and action: deleted
/api/v1.0/beers/<beer id>/favorites - DELETE