Search code examples
pythondjangodjango-haystack

Adding an 'order by' option to Django's Haystack


I'm trying to add a "sort by" option to a ModelSearchForm so you can sort by date, name, etc. As of now, this is what I have. I am currently trying to get it to work with the 'created' field, which is a datetime. The problem is that it isn't ordering at all.

I've tried

class CustomSearchForm(ModelSearchForm):
    order_choices= [('date', 'Date'),
                ('name', 'Name'),
                ('model', 'Model')]
    order = forms.ChoiceField(choices=order_choices, widget=forms.RadioSelect(), initial='date', required=False)
    desc = forms.ChoiceField(choices=[('y', 'Descending'), ('n', 'Ascending')], widget=forms.RadioSelect(), label='', initial='y', required=False)


    def search(self):
        sqs = super(CustomSearchForm, self).search()
        if not self.is_valid():
            return self.no_query_found()

        if self.cleaned_data['order'] == 'date':
            if self.cleaned_data['desc'] == 'y':
                # it successfully gets to this point, but this next line does nothing...
                sqs.order_by('-created')
            else:
                sqs.order_by('created')

        return sqs

I've also tried this:

sqs.order_by('File__created')

Same outcome (no ordering at all.)

In my models file:

class File(models.Model):
    file_sequence = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=100, blank=True)
    folder_sequence = models.ForeignKey(Folders, db_column='folder_sequence')
    created = models.DateTimeField(blank=True, null=True)
    notes = models.TextField(blank=True)

I can not figure it out for the life of me. Am I going about this the wrong way? I'm surprised Haystack doesn't have this functionality built into it already.

Edit: Also, I am using Whoosh as the backend.

search_indexes.py:

class FilesIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.NgramField(document=True, use_template=True)
    created = indexes.DateTimeField(model_attr='created')
    def get_model(self):
        return Files

    def index_queryset(self, using=None):
        """Used when the entire index for model is updated."""
        return self.get_model().objects.all().select_related() 

Solution

  • Wow, I can't believe I missed this.

        if self.cleaned_data['order'] == 'date':
            if self.cleaned_data['desc'] == 'y':
                sqs.order_by('-created')
            else:
                sqs.order_by('created')
    

    needs to be

        if self.cleaned_data['order'] == 'date':
            if self.cleaned_data['desc'] == 'y':
                sqs = sqs.order_by('-created')
            else:
                sqs = sqs.order_by('created')