0

我在 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"),)
4

2 回答 2

0

有一些误解。

首先,您datastore在代码中使用,而不是 django。没有unique_together也没有Meta选项datastore。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)

编辑2:

内置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"),)

编辑3:

这是一个完整的示例,一个用于 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)
于 2013-05-12T04:09:44.350 回答
0

我不熟悉 django,但为了解决您的问题,我只需使用某种数据散列并将其分配为实体的 key_name。这样你就可以保证它是唯一的,并且使用 put hook 来实现一个计数器应该是微不足道的。

于 2013-05-12T04:23:55.033 回答