2013-05-12 5 views
0

사용자가 입력 한 일부 데이터 필드를 저장하는 appengine에 app이 있습니다. 중복 항목을 방지하고 싶습니다. 즉 모든 필드가 동일하면 데이터를 데이터베이스에 입력하지 않아야합니다.Django 모델 메타 옵션 unique_together에 대한 appengine

(선택 사항) 동일한 데이터를 입력하면 해당 열 "값"의 값이 증가합니다.

이 목적으로 Django 메타 옵션 unique_together를 사용해 보았지만 작동하지 않습니다. 동일한 데이터가 여전히 데이터베이스에 저장됩니다. 도와주세요. 여기 내 코드 :

class Log(db.Model): 
    name = db.StringProperty() 
    location = db.StringProperty() 
    msg = db.StringProperty() 
    class Meta: 
     unique_together = (("name","location","msg"),) 

답변

0

약간의 오해가 있습니다.

먼저 코드에서 datastore을 사용하고 django는 사용하지 않습니다. datastore에 대한 unique_together 또는 Meta 옵션이 없습니다. Datastore는 appengine의 nosql 서비스입니다.

데이터 스토어 엔티티를 고유하게 만들려면 다음과 같이하십시오. 가장 쉬운 방법은 key_name을 사용하는 것입니다. key_name은 고유합니다. 나중 엔티티가 이전 엔티티를 대체하지만 동일한 엔티티 인 key_name을 대체합니다. 예를 들어

:

# key_name has length limit (500), hash it can make sure it won't exceed the limit 
log = Log(
    key_name=str(hash((name,location,msg))), 
    name=name, 
    location=location, 
    msg=msg 
) 
log.put() 
# it will replace any exist log which has the same name, location, msg combination. 

# and the item can be Retrieve via key_name directly. 
log = Log.get(key_name) 

EDIT2 :

내장 hash 다른 시스템에 다른 값을 반환 할 수 있습니다. 따라서 hashlib을 대신 사용하는 것이 좋습니다.

여러 가지 방법으로 key_name을 정의 할 수 있습니다. 실수로 충돌하지 않도록하십시오. 예 : md5 : http://docs.python.org/2/library/md5.html 또는 모든 필드를 추가하십시오. 자세한 내용은 key_name=name + "|" + location + "|" + msg

: 당신 앱 엔진에 장고를 사용하려면 https://developers.google.com/appengine/docs/python/datastore/entities#Retrieving_an_Entity

, 모델 정의해야 같은 :

from django.db import models 

class Log(models.Model): 
    name = models.CharField(max_length=255) 
    location = models.StringProperty(max_length=255) 
    msg = models.StringProperty(max_length=255) 
    class Meta: 
     unique_together = (("name","location","msg"),) 

EDIT3 : 여기에

이 완벽한 예입니다 , 하나는 db를위한 것이고 다른 하나는 ndb를위한 것입니다. ndb의 경우 매우 간단합니다. db의 경우 약간 어렵습니다.

from google.appengine.ext import db 
from google.appengine.ext import ndb 
import webapp2 

class Log(db.Model): 
    name = db.StringProperty() 
    location = db.StringProperty() 
    msg = db.StringProperty() 

    count = db.IntegerProperty() 

    @classmethod 
    def key_name(cls, name, location, msg): 
     return name+"|"+location+"|"+msg 

    @classmethod 
    def get(cls, name, location, msg): 
     return db.get(db.Key.from_path(cls.__name__, cls.key_name(name, location, msg))) 

class nLog(ndb.Model): 
    name = ndb.StringProperty() 
    location = ndb.StringProperty() 
    msg = ndb.StringProperty() 

    count = ndb.IntegerProperty() 


class Test1(webapp2.RequestHandler): 
    def get(self): 
     name='test_name' 
     location = 'test_location' 
     msg = 'test_msg' 

     Qkey_name= Log.key_name(name, location, msg) 

     log = Log(
      key_name=Qkey_name, 
      name=name, 
      location=location, 
      msg=msg, 
      count=0 
     ).put() 

     if Log.get(name, location, msg) is not None: 
      Qcount = Log.get(name, location, msg).count 
     else: 
      Qcount = 1 

class Test2(webapp2.RequestHandler): 
    def get(self): 
     name='test_name' 
     location = 'test_location' 
     msg = 'test_msg' 

     Qkey_name = name + "|" + location + "|" + msg 
     log = nLog(
      id=Qkey_name, 
      name=name, 
      location=location, 
      msg=msg, 
      count=0 
     ).put() 

     if nLog.get_by_id(Qkey_name) is not None: 
      Qcount = nLog.get_by_id(Qkey_name).count 
     else: 
      Qcount = 1 



app = webapp2.WSGIApplication([ 
    (r'/1', Test1), 
    (r'/2', Test2) 
    ], debug=True) 
+0

아, 지적 해 주셔서 고맙습니다 :) key_name을 사용하는 방법에 대해 어떤 방향으로 가르쳐 주시겠습니까? –

+0

내 편집을 참조하십시오. 몇 가지 샘플 코드와 데이터 저장소 사용을위한 참조를 추가했습니다. – lucemia

+0

이러한 계몽적인 답변을 주셔서 대단히 감사합니다! –

0

내가 장고에 익숙하지 오전하지만 문제를 해결하기 위해 난 그냥 데이터의 해시의 일종을 사용하고 개체의 KEY_NAME으로 지정합니다. 당신이 보장하는 그런 식으로 그것은 독특 할 것이고, 카운터는 풋 훅을 사용하여 구현하는 것이 간단해야합니다.