We’ve already made sites with templates.
We will make an app that stores (and retrieves!) data on the cloud. In AppEngine land, one of the services that stores and retrives data is called Datastore.
We’re going to learn by doing! Doing the Hogwarts Lab in the curriculum, that is. So clone the CSSI Labs Repository if you have not yet done so. Open up your editor and navigate to
Also, open up the curriculum to the DataStore Intro Page.
The datastore will be holding:
Once the repo is cloned and you have navigated to the directory, get oriented with the project files:
. ├── README.md ├── app.yaml ├── hogwarts_models.py ├── main.py ├── seed_hogwarts_db.py └── templates └── houselist.html
First, let’s all peek at app.yaml and main.py. Ask if there are any structural things in those files you haven’t seen before.
Next, browse the file hogwarts_models.py.
Next, go back to main.py and look more carefully at the
LoadDataHandler. It calls a function. Where does the function that it calls come from? Find that file and browse it too.
In the file seed_hogwarts_db.py, what do you think that:
.put()will write an object into DataStore. Keys are DataStore’s way of identifying an object. The result of
.put()is a key that you can use in your Python code to work with the object you just added. It’s okay to be confused now. If so, revisit the idea after the code along.
STEP 1 Go to proper folder, and:
$ dev_appserver.py app.yaml --clear_datastore=yes --enable_console=True
Note that command was more complex than before, right?
STEP 2 In your browser, go to: http://localhost:8080/seed-data.
STEP 3 Now go to your interactive console, http://localhost:8000/. Practice listing entities. Cross reference with the code in the seed data file.
STEP 4 Delete any code in the interactive console, and enter and run:
from google.appengine.ext import ndb from hogwarts_models import Student, House, Teacher, Enrollment, Wand, Course print(Teacher.query().fetch())
Note something interesting:
.query()makes a query, but
.fetch()gets all the results from the query
STEP 5 Let’s write some queries and learn as we go.
As we encounter these queries, write down some key words that you encounter (e.g., query, fetch, get, count, filter, order, ...)
We will so some together and you can work on some on your own or with a partner. Don’t forget to help each other. Don’t forget the PEP as well.
For CSSI, we use the NDB library, not the Firestore! Documentation is here.
houses = House.query().fetch() for house in houses: print(house.name)
students = Student.query().order(Student.first_name).fetch() for student in students: print(student.first_name + ' ' + student.last_name)
ravenclaw = House.query().filter(House.name == "Ravenclaw").get() print(ravenclaw.mascot)
print(Student.query().filter(Student.last_name == "Weasley").get().student_id)
ravenclaw_students = House.query().filter(House.name == "Slytherin").get().students print(len(ravenclaw_students))
Should there be a better way?
There is a limit of 1000 results from
In general, you should pass a smaller value to
fetchand paginate. But, wait, what does this limit mean for “max” queries?
The first connection is done for you! Look in main.py to see the route, and the actual database call!
Find out the app url before revealing 🙂
snape = Teacher.query().filter(Teacher.name == "Severus Snape").get() print(len(snape.classes_taught))
teachers = Teacher.query().fetch() teacher = max(teachers, key=lambda teacher: teacher.years_experience) print(teacher.name + ' has been teaching ' + str(teacher.years_experience) + ' years')
print(House.query().filter(House.mascot == "Badger").get())
hermione_key = Student.query().filter(Student.first_name == 'Hermione').get().key print(House.query().filter(House.students == hermione_key).get())
The lab is infinitely expandable.
That lab we did...was run locally at localhost:8080 with the development app server. When you run locally, the datastore is actually saved on your machine. In order to really store your data on the cloud, you just have to deploy your app.