title: GAE/Python best practice for a pop-up alert?
body: <p>I need to have an alert pop-up in Google App Engine when the user inputs a value that would create a duplicate item. What is the best way to do this?</p>
  
  <p>I found a way to do it, but it's far from elegant: </p>
  
  <p>When the user inputs a duplicate project code I show a new page "error-message.html" which explains the user what happenned and provides a "back" button. However, I would rather show an alert on the "add-project.html" page. Javascript would be a good idea but it can't validate in the database, so it's no use. </p>
  
  <p>What is the best practice in GAE/Python to show an alert box triggered from code?</p>
  
  <p>So any help or suggestions would be appreciated!</p>
  
  <p>Thanks!</p>
  
  <p>CODE:</p>
  
  <p>The app I'm working on now is a simple project manager's tool. I'm using the webapp2 included with GAE.</p>
  
  <p>Current workflow:
  1) In AddProject I show the user a page to input new project data ("add-project.html). This page is based on a JINJA template. User fills in data and Clicks on submit.
  2) Submit calls SaveAddedProject which checks in the NDB if the project code already exists.
  3) If project code is not in the NDB yet, the new project is saved in the NDB and the code re-directs to the general projects page.
  4) If the project exists I show a new page called "error-message.html" which tells the user he/she is inputting a duplicate value and provides a button to go back. The user can then change his value and retry.</p>
  
  <p>Model:</p>
  
  <pre><code>class Project(ndb.Model):
    # Models and individual Project entry
    proj_id = ndb.StringProperty(required = True)
    proj_desc = ndb.StringProperty(required = True)
    proj_status = ndb.StringProperty(required = True)
  </code></pre>
  
  <p>Dispatchers:</p>
  
  <pre><code>class AddProject(webapp2.RequestHandler):
  # Displays template to fill-in data for new project, 
  # then calls SaveAddedProject
    def post(self):
      user = users.get_current_user() # We use Google's login system
      logout_url = users.create_logout_url(self.request.url)
      template_values = {
          'user_id': user,
          'logout_url': logout_url,
      }
  
      template = JINJA_ENVIRONMENT.get_template('add-project.html')
      self.response.write(template.render(template_values))
  
  class SaveAddedProject(webapp2.RequestHandler):
  # Saves a new project. Is called from AddProject
    def post(self):
      proj_id_str = self.request.get('proj_id')
      proj_desc_str = self.request.get('proj_desc')
      proj_status_str = self.request.get('proj_status')
      # The add template already validates required fields aren't empty :-)
  
      # Verify we don't duplicate the project_id
      pq = Project.query(ancestor = get_projects_key())
      pq = pq.filter(Project.proj_id == proj_id_str)
      pq_result = pq.fetch(limit=1)
      if len(pq_result) &gt; 0:  # Notify the user
              template_values = {'error_message': 'Project ID ' + proj_id_str + ' already exists',
              }
              template = JINJA_ENVIRONMENT.get_template('error-message.html')
              self.response.write(template.render(template_values))
      else:
          # Create new project
          project = Project(parent=get_projects_key()) # Use root ancestor key  
          # Populate fields, save to NDB
          project.proj_id = proj_id_str
          project.proj_desc = proj_desc_str
          project.proj_status = proj_status_str
          project.put()
          self.redirect('/projects')
  </code></pre>
  
  <p>HTML for add-project.html:</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  {% autoescape true %}
  &lt;html&gt;
    &lt;head&gt;
      &lt;link type="text/css" rel="stylesheet" href="/stylesheets/pages.css" /&gt;
      &lt;title&gt;Action List&lt;/title&gt;
      &lt;script&gt;
        function validateForm() {
      var count = 0;
      var x = document.forms["form1"]["proj_id"].value;
      if (x == null || x == "") {
         count = 1;
         }
       var x = document.forms["form1"]["proj_desc"].value;
       if (x == null || x == "") {
         count = 1;
         }
      if (count == 1) {
         document.getElementById('AlertMsg').innerHTML = '&lt;font color="red"&gt;Please fill in all fields marked with *&lt;/font&gt;';
          return false;
         }
       }
  &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h2&gt;Add Project&lt;/h2&gt;
    &lt;br&gt;
    &lt;b&gt;User: {{ user_id }} &lt;/b&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;form name="form1" action="/p-save-add" onsubmit="return validateForm()" method="post"&gt;
      &lt;div&gt;
        ID * &lt;input value="" name="proj_id" size="15"&gt;
       Description * &lt;input value="" name="proj_desc" size="50"&gt;
       Status: &lt;select name='proj_status'&gt;
          &lt;option value='Open'&gt;Open&lt;/option&gt;
          &lt;option value='Closed'&gt;Closed&lt;/option&gt;
        &lt;/select&gt;
      &lt;/div&gt;   
      &lt;br&gt;
      &lt;div&gt;&lt;input type="submit" value="Save"&gt;&lt;/div&gt;
    &lt;/form&gt;
    &lt;br&gt;
    &lt;br&gt;
    &lt;b id='AlertMsg' &gt; &lt;/b&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  {% endautoescape %}
  </code></pre>
  
  <p>HTML for error-message.html:</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  {% autoescape true %}
  
  &lt;script&gt;
  function goBack() {
    window.history.back();
  }
  &lt;/script&gt;
  
  
  &lt;html&gt;
    &lt;head&gt;
      &lt;title&gt;ActionList&lt;/title&gt;
       &lt;link type="text/css" rel="stylesheet"      href="/stylesheets/messages.css" /&gt;
    &lt;/head&gt;
  
  &lt;body&gt;
    &lt;h3&gt; Sorry, an error ocurred!&lt;/h3&gt;    
    {{ error_message }}
    &lt;br&gt;
    &lt;br&gt;
    &lt;button onclick="goBack()"&gt;Back&lt;/button&gt;
  &lt;/body&gt;
  </code></pre>
  
  <p>
    {% endautoescape %}</p>