[컴][웹] 구글 앱 엔진 web app 대신에 Django 이용하기 7 - Django Data Model







기존의 Django 에서 db 에 저장해서 값을 읽어드려 작업을 할 일이 생겼다. 그래서 드디어 model 부분을 작업하게 되었다.


models.py 에 class 추가

기존의 Django 에서는 models.Model 을 extend(상속) 해서 사용하지만, google app engine(GAE) 에서는 db.Model 을 상속해서 사용하면 된다.
여기에 사용되는 type 들은 db.*Property 형태로 제공된다.(ref.3 참조)
여기서는 아래와 같은 model 를 사용할 것이다. 자세한 property 의 특성은 ref. 3 을 참조하자.

class ChartFeed(db.Model):
    name = db.StringProperty()
    date = db.DateTimeProperty(auto_now=True)   # last modified time
    thisweekcontent = db.TextProperty()
    
    
    def __unicode__(self):
        return u'%s' % self.title
        
    def __str__(self):
        return self.__unicode__()



views.py 에 logic 추가

DB를 이용해서 값을 사용할 때는 추출(retreiving), 저장(save), 삭제(delete) 정도만 알면 대부분 해결 된다. DataStore 에서도 이 3가지를 제공한다.

먼저 저장된 값이 있어야 사용할 수 있기 때문에 저장을 한 번 해보자.


put()

저장은 아래와 같은 코드로 가능하다. 대략적으로 보면 알 것이다. 여기서 key_name 은 자신이 정해주는 key 값이다. 특정 값을 정해주게 되면 이 값을 이용해서 나중에 저장한 entity 를 쉽게 불러 올 수 있다.

참고로, 이 저장은 update() 의 기능도 한다. 같은 key 값을 가진 곳에 저장하게 되면 update 가 된다.

이외에 자세한 사항은 ref. 10 을 참조하자.

feed = models.ChartFeed(key_name=chart_id)
feed.name = chart_id
feed.thisweekcontent = db.Text(chartdataString, encoding="utf-8")
feed.put()  # save

DataStore 의 hierarchy

DataStore 는 저장할 때 unique 한 key 를 필요로 한다. 이 key 를 지정해 주지 않으면 NotSavedError 가 발생한다.

DataStore 에서는 entity 를 저장할 때 direcotry 같은 구조를 만들 수 있다. 저장할 때 parent 를 지정해 주는 방식으로 가능한데[ref. 4],

gb 를 root entity 로 하고 이 밑으로 child 를 두고 싶다면

gb = Guestbook()
gb.put()

gb2 = Guestbook(parent=gb) # instance 를 사용하거나.

g_key = gb.key()
gb2 = Guestbook(parent=g_key) # key 를 이용하면 된다.

gb2.put()


로 하면 된다.

db.Key.from_path()

key 를 얻어 오는 방식은 위에서 처럼 instance 에서 key() method 를 호출해도 가능하고, kind(class name 이라고 봐도 무방하다.) 와 name(또는 id, id 는 name 을 지정하지 않았을 때 datastore 에 의해 자동으로 할당되는 녀석이다.[ref. 6,7]) 을 알고 있는 경우에는 아래 함수를 사용해서 얻어 올 수 있다.
db.Key.from_path('Guestbook', 'schoolguestbook')
Guestbook 종류(kind) 에 'schoolguestbook' 이라는 이름을 가진 entity의 key 를 만들어 준다. (이 key 를 간단히 Guestbook : schoolguestbook 이라고 하자.)[ref. 5]

TextProperty()

기본적으로 ascii 가 아닌 녀석을 바로 넣을 수 없다.(assign) 만약 utf-8 으로 된 text 를 TextProperty() 에 assign 을 하려면
db.Text("text", encoding="utf-8")
을 이용해야 한다. 나도 아래와 같이 사용하여서 TextProperty() 에 assign 이 됐다. 그전에는 error 가 ㅜ.ㅜ
feed.thisweekcontent = db.Text(chartdataString, encoding="utf-8")


get(), run()

    chartfeeds = db.GqlQuery("SELECT * "
                      "FROM ChartFeed "
                      "WHERE __key__ = KEY('ChartFeed', :1) AND date < :2",
                       chart_id, datetime.datetime.now())
    chartfeed = chartfeeds.get()
    if chartfeed is not None:
        chartdataString = chartfeed.thisweekcontent

db.GqlQuery() 로 DataStore 에 query 를 날릴 수 있다. 사용법은 ref.7 , ref.8  을 참고하면 될 듯 하다.

여기서 query 를 만들고 나서 .get() 과 .run() 을 통해 실제로 query 를 실행하게 된다. get() 은 바로 첫번째 entity 를 가져오는 것이고, run() 은 흔히 cursor 를 가져온다고 생각하면 되겠다. run() 은 iterable 해서 for 문을 이용해서 전부 출력할 수 있다.[ref. 9]

처음 retrieve 를 할 때는 Datastore 의 index 와 관련해서 문제가 있었다. 이 index 가 index.yaml 에 있는 내용을 가지고 GAE 에서 자동적으로 만들어 내는 무엇인듯 한데 이녀석이 만들어져야 retrieve 가 가능한 듯 하다. 그러니 조금 시간을 두고 다시 실행하면 잘 된다.

만들어 졌는지 여부는 Goolge app engine Console 의 Datastore indexes 에서 확인할 수 있다. 자세한 사항은 [ref. 11] 을 참조하자.

gqlQuery() 에서 bound parameter 사용

ref.8 에서 볼 수 있는 것처럼 gqlQuery 를 다양한 방식으로 만들 수 있다. 이 때 query string 에 들어갈 값을 parameter 에 적고, string 에는 숫자나 이름으로 대체해서 사용할 수 있다. 예를 들면, 1번째 parameter 에 있는 녀석을 참고하려면 ":1" 를 사용하고, composer 라는 이름의 parameter 를 참고하려면, ":composer" 를 사용하는 식이다.
q = GqlQuery("SELECT * FROM Song WHERE composer = 'Lennon, John'")

q = GqlQuery("SELECT __key__ FROM Song WHERE composer = :1", "Lennon, John")

q = GqlQuery("SELECT * FROM Song WHERE composer = :composer", composer="Lennon, John")

delete()

삭제는 원하는 enetity 를 불러와서 삭제하면 된다. 예제는 아래에 있다. 참고로 delete 는 실험해 보지 못했다. ^^;;;

이외에 자세한 사항은 ref. 10 을 참조하자.
    chartfeeds = db.GqlQuery("SELECT * "
                      "FROM ChartFeed "
                      "WHERE __key__ = KEY('ChartFeed', :1) AND date < :2",
                       chart_id, datetime.datetime.now())
    chartfeed = chartfeeds.get()
    if chartfeed is not None:
        chartfeed.delete()



References

  1. http://agiliq.com/dumps/appengine/doc.html#defining-the-datamodel-for-the-blog
  2. https://docs.djangoproject.com/en/dev/topics/db/models/
  3. Types and Property Classes, Google App Engine
  4. https://developers.google.com/appengine/docs/python/datastore/entities#Ancestor_Paths
  5. https://developers.google.com/appengine/docs/python/datastore/keyclass
  6. https://developers.google.com/appengine/docs/python/datastore/entities#Kinds_and_Identifiers
  7. https://developers.google.com/appengine/docs/python/datastore/gqlreference#Examples
  8. https://developers.google.com/appengine/docs/python/datastore/gqlqueryclass?hl=lt#Introduction
  9. https://developers.google.com/appengine/docs/python/datastore/gqlqueryclass?hl=en
  10. https://developers.google.com/appengine/docs/python/datastore/modelclass?hl=en
  11. https://developers.google.com/appengine/kb/general#indexes

댓글 없음:

댓글 쓰기