RotaJota
RotaJota

Reputation: 841

Custom Sorting on Custom Field in Django

In my app, I have defined a custom field to represent a physical quantity using the quantities package.

class AmountField(models.CharField):
    def __init__(self, *args, **kwargs):
        ...

    def to_python(self, value):
        create_quantities_value(value)

Essentially the way it works is it extends CharField to store the value as a string in the database

"12 min"

and represents it as a quantities object when using the field in a model

array(12) * min

Then in a model it is used as such:

class MyModel(models.Model):
    group = models.CharField()
    amount = AmountField()

    class Meta:
        ordering = ['group', 'amount']

My issue is that these fields do not seem to sort by the quantity, but instead by the string.

So if I have some objects that contain something like

they end up sorted something like this:

>>> MyModel.objects.all()
[{A, 12 min}, {A, 2 min}, {A, 20 min}, {B, 1 hr}, {B, 20 min}]

essentially alphabetical order.

Can I give my custom AmountField a comparison function so that it will compare by the python value instead of the DB value?

Upvotes: 3

Views: 1037

Answers (3)

James R
James R

Reputation: 4656

I'm going to go with a totally different approach.

Instead of having a custom field to store what is really time units, why not just store the time units?

For example, 02 minutes, should just be 02. You can either store as integer or, I think there is a TimeField that will allow you to store units in units of time.

You obviously want it to display so a human being can correctly understand that 02 really means 2 mins, so just write a custom filter in your form to deal with the mins or hrs or whatever you might want to add to the end.

This would have other benefits. Let's say you wanted to add all those time units as you had it previously. To do so would require some string processing, and to change that portion of the string to something that has add or sub or the like methods.

Upvotes: 0

Kirill
Kirill

Reputation: 3454

I think there is no way to sort it as numbers. I mean no effective way since I believe Django allows sorting by computational field somehow but you have to compute all the keys to do that. So try to find a way to store numbers as numbers in database. Maybe store quantity as an integer and add method or property for conversion it to quantity object? Something like this:

class MyModel(models.Model):
    group = models.CharField()
    amount = models.IntegerField()  # or PositiveIntegerField

    class Meta:
        ordering = ['group', 'amount']

    def amountAsQuantityObject(self):
        return create_quantities_value(self.amount)

    # or as a property
    quantity_object = property(amountAsQuantityObject)

Upvotes: 1

knabar
knabar

Reputation: 1156

Could you store it with leading zeros in the database?

E.g. "02 min"

That way it would sort correctly and when you parse it out again the leading zeros should not matter.

Upvotes: 0

Related Questions