0

I have the Model Chapter:

class Chapter(ndb.Model):
    tutKey = ndb.KeyProperty(kind='Tutorial')
    title = ndb.StringProperty(required=True)
    content = ndb.TextProperty(required=True)
    note = ndb.TextProperty()
    lvl = ndb.IntegerProperty(default=0)
    order = ndb.IntegerProperty(default=0)
    parentID = ndb.KeyProperty(kind='Chapter')
    number = ndb.IntegerProperty()

'number' is the base chapter (chap1 or chap 1.2 have number = 1). 'lvl' is for the depth of the chapter, for example, in chap1.1.1 the lvl is 3 and in chap1.1.1.1 lvl is 4. And the 'order' says the order of the chap, for example, in chap1.2 'order' is 2 and in chap2.2 'order' is also 2.

How can i sort the following chapters (for example)?

chapter 2
chapter 2.1
chapter 1.1.1
chapter 1.1
chapter 1

I have been thinking... should i create a StringProperty to save the chapter number like "1.2.1" and then split the string by '.' ?


EDIT: i created a ndb.IntegerProperty(repeated=True) the equivalent to ListProperty suggested by JBernardo. I'm able to store the data correctly, but I can't get a way to sort by the property. Anyone knows how to do this?

mFontoura
  • 257
  • 2
  • 15
  • 2
    something like [this](http://stackoverflow.com/questions/2574080/sorting-a-list-of-version-strings) – Fredrik Pihl Feb 13 '13 at 19:53
  • Save it as integers in a [`ListProperty`](https://developers.google.com/appengine/docs/python/datastore/typesandpropertyclasses#ListProperty) – JBernardo Feb 13 '13 at 19:57
  • JBernardo, I'm trying your suggestion, do you know if it is possible to sort a query by a ListPorperty? How? – mFontoura Feb 13 '13 at 23:48

3 Answers3

3

You can represent your chapters by tuples with the length of the maximum depths of sub-chapters. Not used sub-chapters are represented by zeros. Then following would be a representation of your chapters:

chapter 2      (2, 0, 0)
chapter 2.1    (2, 1, 0)
chapter 1.1.1  (1, 1, 1)
chapter 1.1    (1, 1, 0)
chapter 1      (1, 0, 0)

If these chapters are added to a list l, this list can be sorted by the lists' sort method.

chapters = [(2, 0, 0), (2, 1, 0), (1, 1, 1), (1, 1, 0), (1, 0, 0)]
chapters.sort()
print chapters

This gives:

[(1, 0, 0), (1, 1, 0), (1, 1, 1), (2, 0, 0), (2, 1, 0)]

--- EDIT ---

In case of dynamic comparison you can add a function to the sort method via the key option. This function is applied to every element of the list before sorting. In the following expandChapter expands a chapter ch to the depth depth. The key argument in sort accepts only one parameter. Therefore, the maximum depth maxdepth is calculated and expandChapters is given to sort via anonymous lambda function.

def expandChapter(ch, depth):
    ch = ch + (0,) * (depth - len(ch))
    return ch

print expandChapter((1,), 3)                                # prints (1, 0, 0)

chapters = [(2,), (2, 1,), (1, 1, 1,), (1, 1), (1,)]
maxdepth = max([len(i) for i in chapters])
print maxdepth                                              # prints 3

chapters.sort(key = lambda x: expandChapter(x, maxdepth))
print chapters

This gives the correct answer:

[(1,), (1, 1), (1, 1, 1), (2,), (2, 1)]
Holger
  • 2,125
  • 2
  • 19
  • 30
  • that only let me create 3 lvls... right? I want it to be dynamic. I want, if i want, to create a chapter with x lvls for example 1.1.1.1.1 – mFontoura Feb 13 '13 at 22:23
  • Does this answer also applies to this question? http://stackoverflow.com/q/14882833/1601970 also, I don't understand this part:`ch = ch + (0,) * (depth - len(ch))` – mFontoura Feb 15 '13 at 17:40
  • I don't know about google-app-engine and `ListProperty`. It is a pure Python solution. `ch` is the original tuple and the `+` concatenates it with missing zeros. `(0,)*3` would produce `(0, 0, 0)`. – Holger Feb 15 '13 at 20:25
0

The first thing that sprung into my mind was to set up your routes to handle the chapters so to have something like:

1/1
1/2/1

etc

0

Found a simpler way to solve my problem. I store the chapter in a different way. In ndb.IntegerProperty(repeated=True). This way i can sort it just my using:

newChaps = sorted(chaps, key=lambda obj: obj.version)

Where 'version' is the ndb.IntegerProperty.

Done.

mFontoura
  • 257
  • 2
  • 15