Question

I've got a web app that's a simple wiki. It allows users who are logged in to edit existing topics or create new content if that topic doesn't have a page. I have been struggling with creating a version history page that lists the last n edits of a topic along with date/editor. However, I finally succeeded in displaying a list of n previous versions on the history page for a topic. My question is not exactly why what I'm doing now works... but why what I was trying before wasn't working.

Here is the handler class for a 'history' page. It's get method receives the topic as an arg in the form '/topic':

class History(Main):
    """ Display previous versions of a topic if they exist """

    def get(self, topic):
        topic = topic[1:]
        history = Version.get_topic_history(topic).fetch(10)
        if history:
            self.render('history.html', history=history, topic=topic)
        else:
            self.redirect('/%s' % topic)

Here is the model for storing all topic edits. It has a classmethod, get_topic_history. It queries the Version class for all entities by topic name, and then returns them ordered by creation date. This works. However, you can see just above that line, commented out, is what I was doing originally, that didn't work. In the first commented out line, I retrieved the key for all entities with the ancestor path that included the particular topic name(I think this is called an ancestor query, and at least, this is what I understand it to be doing). Then I returned a query by ancestor path, and ordered also by creation date/time. This method is called from the History handler as you can see. This to me, looks like it should have returned the same result as my current approach, yet it returned nothing. Can anyone tell me why? And thanks in advance for all answers.

class Version(ndb.Model):
    """ wiki version history """

    created = ndb.DateTimeProperty(auto_now_add=True)
    author = ndb.StringProperty(required=True)
    topic = ndb.StringProperty(required=True)
    content = ndb.TextProperty(required=True)

    @classmethod
    def get_topic_history(cls, topic):
        # key = ndb.Key(cls, topic, parent=version_key())
        # return cls.query(ancestor=key).order(-cls.created)
        return cls.query(cls.topic == topic).order(-cls.created)

this is how I store the versions:

version = Version(topic=topic,
                  content=content,
                  author=User.get_user_name(self.user_id()),
                  parent=version_key())
version.put()

The version key function assigning parent keys in the code above is outside any class:

def version_key():
    return ndb.Key('Group', 'version_group')

Finally here is a history.html template example. I am using Jinja2:

{% extends "base.html" %}
{% block content %}

Topic edit history :: {{topic}}

<div>
    {% for version in history %}
    <div>
        {{version.content}}<br>
        {{version.created}} - {{version.author}}

        <a href="version/{{topic}}">view</a>
    </div> 
    {% endfor %}
</div> 
{% endblock %}
Était-ce utile?

La solution

When you create the Version entity, the parent is version_key().

When you issue the ancestor query, the ancestor should be version_key() as well. However, you are querying with the ancestor ndb.Key(cls, topic, parent=version_key())

I believe what you want to do is:

cls.query(ancestor=version_key()).filter(topic=topic).order(-cls.created)

btw, having a single ancestor is going to be bad for your future performance of creating Version entities.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top