user2250471
user2250471

Reputation: 1112

Prevent duplicate property in ndb datastore

I'm building a simple newsletter app that collects email addresses. I have a form that sends the email value via ajax to my python app, but I can't, for the life of me, figure out how to see if the email already exists. The below code is currently functional, I just don't know where/how to add the "check for pre-existing entity" stuff.

import webapp2
import json

from google.appengine.ext import ndb

class Email(ndb.Model):
    email = ndb.StringProperty()
    subscribed = ndb.BooleanProperty()

    @staticmethod
    def create(email):
        ekey = ndb.Key("Email", email)
        entity = Email.get_or_insert(ekey)
        if entity.email:  ###
            # This email already exists
            return None
        entity.email = email
        entity.subscribed = True
        entity.put()
        return entity

class Subscribe(webapp2.RequestHandler):
    def post(self):
        add = Email.create(self.request.get('email'))
        success = add is not None 
        self.response.headers['Content-Type'] = 'application/json'   
        obj = {
            'success': success
        } 
        self.response.out.write(json.dumps(obj))


app = webapp2.WSGIApplication([
    webapp2.Route(r'/newsletter/new', Subscribe),
], debug=True)

Upvotes: 0

Views: 613

Answers (2)

shahzeb akram
shahzeb akram

Reputation: 926

Its a good approach to always create a separate model class. I created separate model class and updated your Subscribers class post method it will return false if email exists otherwise it will return true. I hope it will solve your problem.

class EmailModel(ndb.Model):
       email = ndb.StringProperty()
       subscribed = ndb.BooleanProperty()

class Subscribe(webapp2.RequestHandler):
      def post(self):
         email = self.request.get('email')
         entity = EmailModel.query(EmailModel.email == email).get()
         if entity:
             # Duplicate
             check = False
         else:
             add = Email()
             add.email = self.request.get('email')
             add.subscribed = True
             add.put()
             check = True
         if check:
              self.response.headers['Content-Type'] = 'application/json'   
              obj = {
                'success': True
              } 
              self.response.out.write(json.dumps(obj))
         else:
              self.response.headers['Content-Type'] = 'application/json'   
              obj = {
                'success': False
              } 
              self.response.out.write(json.dumps(obj))

Upvotes: 1

minou
minou

Reputation: 16563

Updated answer based on Dan's comment. Dan, thank you for correcting me. Further updated, to respond to updated question.

You can set the email address as the id of the Email entity and use get_or_insert. Here the email storage is redundant because it is the id and also a property. You can probably get rid of this redundancy by checking another property at ### below.

class Email(ndb.Model):
    email = ndb.StringProperty()
    subscribed = ndb.BooleanProperty()

    @staticmethod
    def create(email):
        ekey = ndb.Key("Email", email)
        entity = Email.get_or_insert(ekey)
        if entity.email:  ###
            # This email already exists
            return None
        entity.email = email
        entity.subscribed = True
        entity.put()
        return entity

class Subscribe(webapp2.RequestHandler):
    def post(self):
        add = Email.create(self.request.get('email'))
        success = add is not None 
        self.response.headers['Content-Type'] = 'application/json'   
        obj = {
            'success': success
        } 
        self.response.out.write(json.dumps(obj))

I haven't tested the code above so there may be mistakes but it should lead you down the right path.

Upvotes: 1

Related Questions