RkBlog

Hardware, programming and astronomy tutorials and reviews.

Korzystanie z Datastore w Google App Engine

Opis obsługi bazy danych udostępnianej na serwerach Google App Engine.

Google App Engine oferuje nam "Datastore" - bazę danych, określaną mianem "składowiska danych". Zastosowana baza nie jest relacyjną bazą danych i nie używa języka SQL, co zrodzi zapewne pewne trudności i problemy. Z drugiej strony mamy zapewnioną skalowalność, równoważenie ruchu i replikowanie danych między serwerami.

Struktury danych określane są przez modele, o składni zbliżonej do tej z frameworka Django. Do helloworld/helloworld.py dodaj import:
from google.appengine.ext import db
Następnie zdefiniujemy prosty model dla wpisów księgi gości:
class Greeting(db.Model):
  author = db.UserProperty()
  content = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)

Mamy klasę Greeting definiującą strukturę złożoną z trzech pól - author przechowujące obiekty User, content przechowujące dane tekstowe i date dla danych typu datetime.datetime. Niektóre "pola" przyjmują dodatkowe argumenty pozwalające skonfigurować ich zachowanie. W tym przykładzie dla db.StringProperty zastosowaliśmy multiline=True, dzięki czemu dopuszczone będą dane zawierające przejścia do nowej linii. Podanie argumentu auto_now_add=True dla db.DateTimeProperty spowoduje wstawienie obecnej daty, jeżeli nie zostanie podana inna.

Teraz zmodyfikuj klasę "Guestbook" do postaci:
class Guestbook(webapp.RequestHandler):
  def post(self):
    greeting = Greeting()

    if users.get_current_user():
      greeting.author = users.get_current_user()

    greeting.content = self.request.get('content')
    greeting.put()
    self.redirect('/')

Tworzymy w niej obiekt "Greeting", do którego przypisujemy wartości i zapisujemy za pomocą greeting.put().

Dla pobierania danych dostępny jest język GQL - zbliżony składnią do języka SQL. Nie jest to jednak pełna implementacja, a to ze względu na nierelacyjny charakter bazy danych. Zmień kod klasy MainPage na poniższy:
class MainPage(webapp.RequestHandler):
  def get(self):
    self.response.out.write('<html><body>')

    greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")

    for greeting in greetings:
      if greeting.author:
        self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname())
      else:
        self.response.out.write('An anonymous person wrote:')
      self.response.out.write('<blockquote>%s</blockquote>' %
                              cgi.escape(greeting.content))

    # Write the submission form and the footer of the page
    self.response.out.write("""
          <form action="/sign" method="post">
            <div><textarea name="content" rows="3" cols="60"></textarea></div>
            <div><input type="submit" value="Sign Guestbook"></div>
          </form>
        </body>
      </html>""")
Teraz wpisy zapisują się w bazie, a na stronie głównej będziemy widzieć już dodane. W przypadku lokalnego serwera dane przetrzymywane są w plikach tymczasowych. Zapytanie wykonywane jest tak:
greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")
Choć można też wywołać metodę "gql" na klasie "Greeting":
greetings = Greeting.gql("ORDER BY date DESC LIMIT 10")
Zapytania zawsze zwracają pełny obiekt danych i podawanie określonych właściwości obiektów do pobrania nie ma sensu, zawsze będzie to "SELECT * FROM". Zapytania GQL mogą mieć klauzulę WHERE, lecz nie mogą zawierać one stałych wartości dla warunków. Parametry muszą być przypisane, np:
    if users.get_current_user():
      greetings = Greeting.gql("WHERE author = :1 ORDER BY date DESC",
                               users.get_current_user())
Można też stosować nazwy dla przypisywania argumentów:
      greetings = Greeting.gql("WHERE author = :author ORDER BY date DESC",
                               author=users.get_current_user())
API Datastore dostarcza także inny mechanizm zapytań. Powyższe zapytanie można zapisać też tak:
      greetings = Greeting.all()
      greetings.filter("author =", users.get_current_user())
      greetings.order("-date")
RkBlog

14 September 2008;

Comment article