Dzisiaj dalej kontynuuję poznawania możliwości jakie daje Goolge App Engine (w skrócie GAE). W moim ostatnim wpisie pokazałem jak utworzyć prostą aplikację opartą o szkielet webapp oraz użycie usług jakie dostarcza GAE. Dzisiaj na tapetę wezmę ORM jaki dostarcza GAE, przy którym Hibernate może się schować!
Oczywiście dostępnych usług jest więcej niż tylko wspomniany Users Services, zostały one podzielone na kilka typów:
Jak widać jest tego sporo, jednak dzisiaj skoncentruje się na mechaniźmie Datastore, aby nie przedłużać, trochę kodu, który poddam analizie.
import cgi from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app from google.appengine.ext import db
pierwszy krok to dodanie odpowiedniej przestrzeni nazwa do aplikacji, ostatnia linijka uzbraja aplikację w mechanizm ORM, czas zdefiniować klasę
class Greeting(db.Model): author = db.UserProperty() content = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True)
Klasa Greeting dziedziczy po klasie Model z przestrzeni nazw db, jeśli będzie inaczej, obiektów takiej klasy nie da sie zapisać do bazy danych. Koniec i kropka.
Druga sprawa to właściwości klasy są predefiniowanymi typami danych dostarczanymi przez Datastore i jak widać mogą przyjmować parametry w celu ustalenia pewnych specyficznych cech dla danego typu właściwości, więcej szczegółów można znaleźć w dokumentacji.
Z ciekawostek jakie można wyczytać z dokumentacji, to od razu z pudełka otrzymujemy transakcyjność, skalowalność oraz optymalizację, którą zajmuje się sam App Engine! A co ciekawe Datastore nie jest relacyjną bazą danych! Specjalista od bazy danych idzie do zwolnienia ;-)
Skoro nie jest to baza danych, to od tej pory będę używał określenia Składnica danych albo krócej Składnica, idąc za przykładem Jacka do spolszczania czego się da ;-)
No dobrze, mam swoją klasę dziedzinową, ale jak ją pobrać ze Składnicy? Z pomocą przychodzi GQL, czyli język zapytań podobny do SQLa. Poniżej implementacja strony głównej aplikacji, która obsługuje żądanie GET.
class MainPage(webapp.RequestHandler): def get(self): greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10") for greeting in greetings: self.response.out.write(greeting.author.nickname() % ?<br/>?) self.response.out.write(cgi.escape(greeting.content))
Z tego co widać GQL jest faktycznie prosty i podobny do SQLa, trzeba jedynie pamiętać o nazwie klasy, do której się odwołujemy. Bez zbędnych "udziwniaczy" możemy odwoływać się do danych w Składnicy i mapować je do postaci obiektowej. To się nazywa minimalistyczna konfiguracja :D
Oczywiście łatwo o pomyłkę w nazwie klasy, aby to wyeliminować można użyć poniższego mechanizmu, gdzie będziemy mieć pewność, że operacje zostaną wykonane na odpowiednim obiekcie
greetings = Greeting.gql("ORDER BY date DESC LIMIT 10")
Możliwe są nawet bardziej "obiektowe" operacje, gdzie możemy zapomnieć o SQLu
greetings = Greeting.all() greetings.filter("author =", users.get_current_user()) greetings.order("-date")
Czyż nie jest to piękna konstrukcja?
No dobrze, ale co z tworzeniem obiektu i zapisywaniem go w Składnicy?
class Guestbook(webapp.RequestHandler): def post(self): greeting = Greeting() greeting.author = users.get_current_user() greeting.content = self.request.get('content') greeting.put() self.redirect('/')
Powyższy kod definiuje kolejną stronę w aplikacji, tym razem strona obsługuje żądanie POST, w ramach którego tworzone jest nowy obiekt, ustawiane są właściwości, a następnie sam się zapisuje w Składnicy. Dla purystów obiektowych istnieje możliwość użycia bardziej naturalnego mechanizmu:
db.put(greeting)
I znów nic skomplikowanego, utworzyć obiekt i umieścić go w Składnicy, a wszystko to w ramach transakcji, w rozproszonej architekturze GAE.
Na koniec warto podać jak wyczyścić lokalną Składnice na naszym komputerze
dev_appserver.py --clear_datastore helloworld/
I to jest kolejna duża zaleta GAE, nawet nie musimy łączyć się z serwerem, czy też konfigurować lokalną bazę danych aby móc korzystać z mechanizmu persystancji!
I jak tu nie napisać, że w porównaniu do takiego kolosa jak Hibernate, czy też JPA, podejście GAE jest wprost genialne w swojej prostocie. Nawet podejście jakie prezentuje Grails, namiętnie opisywany przez Jacka, nie daje tej "lekkości".
Nie wspomniałem o wielu możliwościach jakie daje Datastore, najbardziej chyba ciekawa to Expando Model, czyli model samorozszerzalny, gdzie nowe właściwości definiujemy w locie! A takich ciekawostek jest więcej, wystarczy przeglądnąć dokumentację.
Pozostało mi omówić mechanizm szablonów i serwowania statycznych plików, a później pozostanie napisanie jakiejś konkretnej aplikacji.
Pozdrawiam
--
Łukasz
http://www.lenart.org.pl/
Comments
Nie ja, tylko autorzy "Beginning Groovy and Grails"
Nie ja, tylko autorzy "Beginning Groovy and Grails". Ja jedynie relacjonuję, co w książce. Moje wypociny przyjdą później, kiedy nabędę trochę ogłady z Grails (i Groovy). Pewnie niebawem(TM).
Jacek
Expando są również w Groovy!
Czytam i widzę ile podobieństw mają Jython i Groovy - najbardziej chyba ciekawa to Expando Model, czyli model samorozszerzalny, gdzie nowe właściwości definiujemy w locie!. W Groovy mamy również Expando! Pisałem o tym w Relacja z rozdziału 3. "More Advanced Groovy" z "Beginning Groovy and Grails" oraz jest opisane w javadoc groovy.util.Expando.
Już doczekać się nie mogę tej konkretnej aplikacji GAE.
Jacek
Ale gafa z tym Expando,
Ale gafa z tym Expando, jakoś ten rozdział umknął mojej uwadze, zresztą sam potraktowałeś go trochę po "macoszemu" ;-)
Pozdrawiam
--
Łukasz
httpL//www.lenart.org.pl/