【问题标题】:Django model Meta option unique_together for appengineappengine 的 Django 模型元选项 unique_together
【发布时间】:2013-05-06 10:02:38
【问题描述】:

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

【问题讨论】:

    标签: django google-app-engine django-models


    【解决方案1】:

    有一些误会。

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

    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)
    

    【讨论】:

    • 哦,非常感谢您指出这一点 :) 能否请您指出一些有关如何使用 key_name 的方向?
    • 请看我的编辑。我为数据存储的使用添加了一些示例代码和参考
    • 非常感谢您这么有启发性的回答!
    • 为此使用内置哈希函数可能不是一个好主意。见:stackoverflow.com/questions/7646520/…
    • @lucemia 非常感谢。真的。你回答完美。我想知道为什么官方 appengine 文档没有这么好的例子:)
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2016-01-12
      • 1970-01-01
      • 2016-08-17
      • 1970-01-01
      • 2010-12-27
      • 2012-01-05
      • 2011-11-23
      • 2017-12-08
      • 2023-01-07
      相关资源
      最近更新 更多