2

I have a document that is built of sections, subsections, and clauses.

Section 1
Subsections 1.1, 1.2, 1.3
Clauses 1.1.1, 1.1.2... 1.2.1, 1.2.2...

They are models that have a "number" field to hold the identifier, but this field is a CharField because of the double dot syntax of some of the subsections and clauses, eg...

Clause 1.2.1

If I want to sort the subsections, Django basic sorting algorithm will sort:

1.1
1.2
1.3
...

But it becomes problematic when I have more than 9 subsections or clauses in a group because sorting gives me:

1.1
1.10
1.11
1.2
1.3
...

Is there a way to have these ordered correctly in template, like:

1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
1.10
1.11 

I could convert them into floats and then sort them - but this wouldn't work for the clauses.

models.py

 class Section(models.Model):
     number = models.CharField(max_length=2, unique=True)
     name = models.CharField(max_length=150, unique=False)
     descriptor = HTMLField(blank=True)

     def __str__(self):
         return u'%s %s' % (self.number, self.name)
     ...

 class Subsection(models.Model):
     number = models.CharField(max_length=5, unique=True)
     name = models.CharField(max_length=150, unique=False)
     descriptor = HTMLField(blank=True)
     fundamental = models.BooleanField()
     section = models.ForeignKey(Section, on_delete=models.DO_NOTHING)

     def __str__(self):
         return u'%s %s' % (self.number, self.name)

     class Meta:
         ordering = ["number"]
     ....

class Clause(models.Model):
    number = models.CharField(max_length=8, unique=True)
    requirements = HTMLField()
    audit_part = models.CharField(max_length=64, choices=AUDIT_CHOICES)
    subsection = models.ForeignKey(Subsection, on_delete=models.DO_NOTHING)
    compliance_level = models.CharField(max_length=64, choices=LEVEL_CHOICES, blank=True, null=True)

    def __str__(self):
        return u'%s' % (self.number)

    class Meta:
        ordering = ["number"]
    ...
kjarsenal
  • 934
  • 1
  • 12
  • 35
  • How are these stored? Please show the models. – Daniel Roseman May 08 '19 at 19:28
  • If you define the comparison functions on your model (e.g. `__gt__()`, `__lt__()`, etc.) it might solve the problem (see [this related answer](https://stackoverflow.com/questions/41694608/define-sorting-key-on-django-model)) – Green Cloak Guy May 08 '19 at 19:33
  • Basic class with one string property: `class v(): def __init__(self,n): self.n = n` -a list of said instances: `k = [v("1.1"),v("1.10"),v("1.11"),v("1.2"),v("1.3")]` - sort them correctly: `s = sorted (k, key = lambda x: tuple(( int(a) for a in x.n.split("."))))` .. result: `['1.1', '1.2', '1.3', '1.10', '1.11']` – Patrick Artner May 08 '19 at 19:41
  • You can use the same logic to fill the `__gt__(self)` / `__lt__(self)` methods of your model - simply split the text field into a tuple of intsand compare them against the same of _other_: `return tuple(( int(a) for a in self.your_text_property.split(".")) > tuple(( int(a) for a in other.your_text_property.split("."))` – Patrick Artner May 08 '19 at 19:45
  • 1
    @PatrickArtner i think the main idea is to do it by orm – Brown Bear May 08 '19 at 20:15
  • 1
    @bear _I could convert them into floats and then sort them - but this wouldn't work for the clauses._ - it works if you convert the sections to tuples of int and sort the tuples. – Patrick Artner May 08 '19 at 20:34

1 Answers1

2

Here's one approach to sorting it that way

from distutils.version import StrictVersion
subs = list(Subsection.objects.all().values_list("number", flat=True))
subs.sort(key=StrictVersion)
print subs

Assuming that subs was ["1.1", "1.10","1.11","1.2","1.3"]

This should give you ['1.1', '1.2', '1.3', '1.10', '1.11']


To sort the queryset

subs = Subsection.objects.all()
result = sorted(subs, key=lambda x: StrictVersion(x.number))
NS0
  • 6,016
  • 1
  • 15
  • 14
  • This creates a list from the item 'numbers' in the queryset and correctly orders them, but it doesn't help me actually order the items in the queryset, and pass that ordered queryset to the template. – kjarsenal May 08 '19 at 20:10