2013-05-12 1 views
0

J'ai une application sur appengine qui stocke certains champs de données entrées par l'utilisateur. Je souhaite empêcher les entrées redondantes, c'est-à-dire si tous les champs sont identiques, les données ne doivent pas être saisies dans la base de données. (Facultatif) Si des données identiques sont entrées, la valeur d'une colonne "count" correspondante doit être incrémentée.Django modèle Meta option unique_together pour appengine

J'ai essayé d'utiliser l'option Django Meta unique_together à cette fin, mais cela ne semble pas fonctionner. Les données identiques sont toujours stockées dans la base de données. S'il vous plaît aider. Voici mon code:

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

Répondre

0

Il y a un malentendu.

Tout d'abord, vous utilisez datastore dans votre code, pas django. Il n'y a pas d'options pour datastore. Datastore est un service nosql sur appengine.

Si vous souhaitez que l'entité du magasin de données soit unique. Le plus simple est d'utiliser key_name. nom_clé sera unique. L'entité ultérieure remplacera l'ancienne alors qu'ils ont la même key_name.

Par exemple:

# 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:

intégré hash peut retourner la valeur différente machine différente. Il est donc préférable d'utiliser hashlib à la place.

Vous pouvez définir votre key_name de plusieurs façons, assurez-vous qu'il ne risque pas de collision en cas d'accident. par exemple: md5: http://docs.python.org/2/library/md5.html ou simplement ajouter tous les champs ensemble. key_name=name + "|" + location + "|" + msg

pour plus d'informations: https://developers.google.com/appengine/docs/python/datastore/entities#Retrieving_an_Entity

Si vous souhaitez utiliser django sur le moteur d'application, le modèle devrait être défini comme:

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:

Voici un exemple complet , un pour db et l'autre pour ndb. Pour ndb, c'est assez simple. Pour DB, c'est un peu dur.

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

Oh, merci beaucoup d'avoir signalé cela :) Pouvez-vous me montrer du doigt comment utiliser key_name? –

+0

s'il vous plaît voir mon edit. J'ai ajouté quelques exemples de code et de références pour l'utilisation du datastore. – lucemia

+0

Merci beaucoup pour cette réponse si éclairante! –

0

Je ne suis pas familier avec django mais pour résoudre votre problème, je voudrais simplement utiliser une sorte de hachage des données et l'affecter comme key_name de l'entité. De cette façon, vous êtes certain que ce sera unique, et un compteur devrait être trivial à implémenter en utilisant un hook.

Questions connexes