2013-05-12 77 views
0

我有一個應用程序在appengine存儲一些數據字段由用戶輸入。我想防止多餘的條目,即如果所有字段都是相同的,則不應將數據輸入到數據庫中。Django模型Meta選項unique_together爲appengine

(可選)如果輸入相同的數據,則應遞增相應列「count」的值。

我嘗試使用Django Meta選項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_togetherMeta選項。 數據存儲是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

如果你想使用的應用程序引擎的Django,模型應該被定義爲:

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? – 2013-05-12 04:15:53

+0

請參閱我的編輯。我已經添加了一些示例代碼和參考數據存儲使用 – lucemia 2013-05-12 04:27:11

+0

非常感謝你這樣一個啓發性的答案! – 2013-05-12 04:37:47

0

我不熟悉Django的,但解決你的問題,我只想使用某種數據的哈希並將其指定爲實體的KEY_NAME。這樣你就可以保證它是唯一的,並且使用put hook來實現一個計數器應該是微不足道的。