|
30 | 30 | from flask import Flask, jsonify, request, url_for, make_response, abort
|
31 | 31 | from flask_api import status # HTTP Status Codes
|
32 | 32 | from werkzeug.exceptions import NotFound
|
33 |
| -from models import Pet, DataValidationError |
| 33 | +#from models import Pet, DataValidationError |
| 34 | + |
| 35 | +# For this example we'll use SQLAlchemy, a popular ORM that supports a |
| 36 | +# variety of backends including SQLite, MySQL, and PostgreSQL |
| 37 | +from flask_sqlalchemy import SQLAlchemy |
34 | 38 |
|
35 | 39 | # Create Flask application
|
36 | 40 | app = Flask(__name__)
|
37 | 41 |
|
| 42 | +# We'll just use SQLite here so we don't need an external database |
| 43 | +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db/development.db' |
| 44 | +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
| 45 | +app.config['SECRET_KEY'] = 'please, tell nobody... Shhhh' |
| 46 | +app.config['LOGGING_LEVEL'] = logging.INFO |
| 47 | + |
| 48 | +# Initialize SQLAlchemy |
| 49 | +db = SQLAlchemy(app) |
| 50 | + |
38 | 51 | # Pull options from environment
|
39 | 52 | DEBUG = (os.getenv('DEBUG', 'False') == 'True')
|
40 | 53 | PORT = os.getenv('PORT', '5000')
|
41 | 54 |
|
| 55 | +class DataValidationError(Exception): |
| 56 | + """ Used for an data validation errors when deserializing """ |
| 57 | + pass |
| 58 | + |
42 | 59 | ######################################################################
|
43 | 60 | # Error Handlers
|
44 | 61 | ######################################################################
|
@@ -83,6 +100,136 @@ def internal_server_error(error):
|
83 | 100 | return jsonify(status=500, error='Internal Server Error', message=message), 500
|
84 | 101 |
|
85 | 102 |
|
| 103 | +######################################################################### |
| 104 | +class Pet(db.Model): |
| 105 | + """ |
| 106 | + Class that represents a Pet |
| 107 | +
|
| 108 | + This version uses arelational database for persistence |
| 109 | + """ |
| 110 | + logger = logging.getLogger(__name__) |
| 111 | + |
| 112 | + # Table Schema |
| 113 | + id = db.Column(db.Integer, primary_key=True) |
| 114 | + name = db.Column(db.String(63)) |
| 115 | + category = db.Column(db.String(63)) |
| 116 | + available = db.Column(db.Boolean()) |
| 117 | + |
| 118 | + # def __init__(self, id=0, name='', category=''): |
| 119 | + # """ Initialize a Pet """ |
| 120 | + # self.id = id |
| 121 | + # self.name = name |
| 122 | + # self.category = category |
| 123 | + |
| 124 | + |
| 125 | + def __repr__(self): |
| 126 | + return '<Pet %r>' % (self.name) |
| 127 | + |
| 128 | + def save(self): |
| 129 | + """ |
| 130 | + Saves a Pet to the data store |
| 131 | + """ |
| 132 | + if not self.id: |
| 133 | + db.session.add(self) |
| 134 | + db.session.commit() |
| 135 | + |
| 136 | + def delete(self): |
| 137 | + """ Removes a Pet from the data store """ |
| 138 | + db.session.delete(self) |
| 139 | + db.session.commit() |
| 140 | + |
| 141 | + def serialize(self): |
| 142 | + """ Serializes a Pet into a dictionary """ |
| 143 | + return {"id": self.id, |
| 144 | + "name": self.name, |
| 145 | + "category": self.category, |
| 146 | + "available": self.available} |
| 147 | + |
| 148 | + def deserialize(self, data): |
| 149 | + """ |
| 150 | + Deserializes a Pet from a dictionary |
| 151 | +
|
| 152 | + Args: |
| 153 | + data (dict): A dictionary containing the Pet data |
| 154 | + """ |
| 155 | + if not isinstance(data, dict): |
| 156 | + raise DataValidationError('Invalid pet: body of request contained bad or no data') |
| 157 | + try: |
| 158 | + self.name = data['name'] |
| 159 | + self.category = data['category'] |
| 160 | + self.available = data['available'] |
| 161 | + except KeyError as error: |
| 162 | + raise DataValidationError('Invalid pet: missing ' + error.args[0]) |
| 163 | + except TypeError as error: |
| 164 | + raise DataValidationError('Invalid pet: body of request contained' \ |
| 165 | + 'bad or no data') |
| 166 | + return self |
| 167 | + |
| 168 | + @staticmethod |
| 169 | + def init_db(): |
| 170 | + """ Initializes the database session """ |
| 171 | + Pet.logger.info('Initializing database') |
| 172 | + db.create_all() # make our sqlalchemy tables |
| 173 | + |
| 174 | + @staticmethod |
| 175 | + def all(): |
| 176 | + """ Returns all of the Pets in the database """ |
| 177 | + Pet.logger.info('Processing all Pets') |
| 178 | + return Pet.query.all() |
| 179 | + |
| 180 | + @staticmethod |
| 181 | + def find(pet_id): |
| 182 | + """ Finds a Pet by it's ID """ |
| 183 | + Pet.logger.info('Processing lookup for id %s ...', pet_id) |
| 184 | + return Pet.query.get(pet_id) |
| 185 | + |
| 186 | + @staticmethod |
| 187 | + def find_or_404(pet_id): |
| 188 | + """ Find a Pet by it's id """ |
| 189 | + Pet.logger.info('Processing lookup or 404 for id %s ...', pet_id) |
| 190 | + return Pet.query.get_or_404(pet_id) |
| 191 | + |
| 192 | + @staticmethod |
| 193 | + def find_by_name(name): |
| 194 | + """ Returns all Pets with the given name |
| 195 | +
|
| 196 | + Args: |
| 197 | + name (string): the name of the Pets you want to match |
| 198 | + """ |
| 199 | + Pet.logger.info('Processing name query for %s ...', name) |
| 200 | + return Pet.query.filter(Pet.name == name) |
| 201 | + |
| 202 | + @staticmethod |
| 203 | + def find_by_category(category): |
| 204 | + """ Returns all of the Pets in a category |
| 205 | +
|
| 206 | + Args: |
| 207 | + category (string): the category of the Pets you want to match |
| 208 | + """ |
| 209 | + Pet.logger.info('Processing category query for %s ...', category) |
| 210 | + return Pet.query.filter(Pet.category == category) |
| 211 | + |
| 212 | + @staticmethod |
| 213 | + def find_by_availability(available=True): |
| 214 | + """ Query that finds Pets by their availability """ |
| 215 | + """ Returns all Pets by their availability |
| 216 | +
|
| 217 | + Args: |
| 218 | + available (boolean): True for pets that are available |
| 219 | + """ |
| 220 | + Pet.logger.info('Processing available query for %s ...', available) |
| 221 | + return Pet.query.filter(Pet.available == available) |
| 222 | + |
| 223 | +######################################################################### |
| 224 | + |
| 225 | + |
| 226 | + |
| 227 | + |
| 228 | + |
| 229 | + |
| 230 | + |
| 231 | + |
| 232 | + |
86 | 233 | ######################################################################
|
87 | 234 | # GET INDEX
|
88 | 235 | ######################################################################
|
@@ -190,6 +337,10 @@ def delete_pets(pet_id):
|
190 | 337 | # U T I L I T Y F U N C T I O N S
|
191 | 338 | ######################################################################
|
192 | 339 |
|
| 340 | +def init_db(): |
| 341 | + """ Initialies the SQLAlchemy app """ |
| 342 | + Pet.init_db() |
| 343 | + |
193 | 344 | def check_content_type(content_type):
|
194 | 345 | """ Checks that the media type is correct """
|
195 | 346 | if request.headers['Content-Type'] == content_type:
|
@@ -222,6 +373,9 @@ def initialize_logging(log_level=logging.INFO):
|
222 | 373 | # M A I N
|
223 | 374 | ######################################################################
|
224 | 375 | if __name__ == "__main__":
|
225 |
| - print "Pet Service Starting..." |
| 376 | + print "=========================================" |
| 377 | + print " P E T S E R V I C E S T A R T I N G" |
| 378 | + print "=========================================" |
226 | 379 | initialize_logging(logging.INFO)
|
| 380 | + db.create_all() # make our sqlalchemy tables |
227 | 381 | app.run(host='0.0.0.0', port=int(PORT), debug=DEBUG)
|
0 commit comments