0

This is a fragment of my tips.html template, included in index.html:

{% for t in tips %}
<div class="col-lg-4 col-sm-6">          
  <form action="comment.html" method="get" class="portfolio-box">
    <img src="img/portfolio/4.jpg" class="img-responsive" alt="">
    <div class="portfolio-box-caption">
      <div class="portfolio-box-caption-content">
        <div class="project-category text-faded">
          {{ t.title }}
        </div>
        <div class="project-name">
          {{ t.content }}                                                                       
        </div>
        <div><br /></div>
        {% if user != 'None' %}
          <input type="hidden" name="tipTitle" value="{{ t.title }}">
          <input type="hidden" name="tipContent" value="{{ t.content }}">
          <input type="hidden" name="hparam" value="tips">
          <div><button class="btn btn-default btn-l wow tada">Explore</button></div>
        {% endif %}
        </div>
      </div>
    </form>          
   </div>
{% endfor %}

This block of html should display the tips available in the datastore. But after I add the first tip to the datasore, and I redirect the response from addtip.html to index.html I get only a div with a picture but no {{ t.title }} nor {{ t.content }} until I refresh the page.

I'm passing Tip.all() to index.html as tips.

models.py

from google.appengine.ext import db
class User(db.Model):
    fullName = db.StringProperty()
    username = db.StringProperty()
    email = db.StringProperty()    
    password = db.StringProperty()
    def getKey(self):
        return self.key()    
class Tip(db.Model):
    title = db.StringProperty()
    content = db.StringProperty(multiline=True)
    date = db.DateTimeProperty(auto_now_add=True)
    img = db.BlobProperty()
    user = db.ReferenceProperty(User, collection_name='tips') 
    def getKey(self):
        return self.key()    
class Comment(db.Model):
    content = db.StringProperty(multiline=True)
    date = db.DateTimeProperty(auto_now_add=True)
    user = db.ReferenceProperty(User, collection_name='comments')
    tip = db.ReferenceProperty(Tip, collection_name='comments')

my handler

class MainPage(BaseHandler):         
    def get(self):        
        template = JINJA_ENVIRONMENT.get_template('index.html')
        query = Tip.all()            
        context = {                   
                'title' :'OutgoingIndex - ' + currentUser.username,
                'user' : currentUser.username,
                'tips' : query
                }
        self.response.write(template.render(context))
Dan McGrath
  • 41,220
  • 11
  • 99
  • 130
Motassem Jalal
  • 1,254
  • 1
  • 22
  • 46

1 Answers1

2

Looks like you're being victim of Eventual Consistency:

Consistency in the context of the GAE datastore, and in very simple, non-technical, terms, is 'availability of the latest copy of the data'. Perhaps a more intutive (but blatantly incorrect) definition would be the 'lack of lag between writes and reads'. Strongly consistent means minimal to no lag, where written data is instantly available for a subsequent read. Eventually consistent means there is considerable lag, where written data will be 'eventually' available to reads after it has been propagated and stored in multiple datacenters.

So what happens is that you are going back to the list of tips just after the write was done, but before it propagated, so the data is not in the index at that moment. If you wait a few seconds before redirect, or refresh as you did, the data will be there.

This is normal, and something you'll get used to. The datastore however guarantees strongly consistent queries if you use an ancestor query. If you're new to this topic, this article could be interesting: Balancing Strong and Eventual Consistency with Google Cloud Datastore.

Jaime Gómez
  • 6,961
  • 3
  • 40
  • 41