Choose how to order Django Model choices

Viewed 40

When displaying the below choices, I want to be able to order them as follows Preparation, Review, Update, Finalised and Completed.

Right now, they are ordered alphabetically.

The below is a simple model:

class Choice(models.Model):
status_choices = [
        ("", "Select Current Status"),
        ("Preparation", "Preparation"),
        ("Review", "Review"),
        ("Update", "Update"),
        ("Finalised", "Finalised"),
        ("Completed", "Completed"),
    ]

    current_status = models.CharField(
        max_length=32,
        choices = status_choices,
        default = "Select current status",
    )

    class Meta:
            ordering = ["current_status"]

I read that assigning a number in the Tuple can allow them to be ordered, which I tried per the below:

status_choices = [
        ("", "Select Current Status"),
        ("1", "Preparation"),
        ("2", "Review"),
        ("3", "Update"),
        ("4", "Finalised"),
        ("5", "Completed"),
    ]

However, this made no difference. I have also tried:


    PREPARATION = "a"
    REVIEW = "b"
    UPDATE = "c"
    FINALISED = "d"
    COMPLETED = "e"

    status_choices = [
        ("", "Select Current Status"),
        (PREPARATION, "Preparation"),
        (REVIEW, "Review"),
        (UPDATE, "Update"),
        (FINALISED, "Finalised"),
        (COMPLETED, "Completed"),
    ]

I feel like this should be very simple but maybe not.

1 Answers

I'm not 100% sure how ordering of numerals in charfields goes, but you might try making the number explicit by changing the field to a smallintegerfield like so:

class Choice(models.Model):

PREPARATION = 1
REVIEW = 2
UPDATE = 3
FINALISED = 4
COMPLETED = 5

status_choices = [
        ("", "Select Current Status"),
        (PREPARATION, "Preparation"),
        (REVIEW, "Review"),
        (UPDATE, "Update"),
        (FINALISED, "Finalised"),
        (COMPLETED, "Completed"),
    ]

    current_status = models.SmallIntegerField(
        choices = status_choices,
        default = 0
    )

    class Meta:
            ordering = ["current_status"]

One advantage of this approach is that you can use a more readable reference to the model's constant while still having the benefits of the numeric ordering, eg,

 if choice_instance.current_status > Choice.UPDATE:

I wasn't sure from your question if you were also having problems with the ordering of the select widget itself. If the above doesn't help with the widget, you might try explicitly referring to the status_choices list, eg,

  widgets = {
        'current_status' : forms.Select(choices = Choice.status_choices, attrs={'placeholder':'Select Current Status', 'class':'table_data_request_status'}),
        }
Related