titleistfour
titleistfour

Reputation: 305

Django Haystack custom SearchView for pretty urls

I'm trying to setup Django Haystack to search based on some pretty urls. Here is my urlpatterns.

urlpatterns += patterns('',
    url(r'^search/$', SearchView(), 
        name='search_all',
    ),
    url(r'^search/(?P<category>\w+)/$', CategorySearchView(
            form_class=SearchForm,
        ), 
        name='search_category',
    ),
)

My custom SearchView class looks like this:

class CategorySearchView(SearchView):
    def __name__(self):
        return "CategorySearchView"

    def __call__(self, request, category):
        self.category = category
        return super(CategorySearchView, self).__call__(request)

    def build_form(self, form_kwargs=None):
        data = None
        kwargs = {
            'load_all': self.load_all,
        }
        if form_kwargs:
            kwargs.update(form_kwargs)

        if len(self.request.GET):
            data = self.request.GET

        kwargs['searchqueryset'] = SearchQuerySet().models(self.category)

        return self.form_class(data, **kwargs)

I keep getting this error running the Django dev web server if I try and visit /search/Vendor/q=Microsoft

UserWarning: The model u'Vendor' is not registered for search.
  warnings.warn('The model %r is not registered for search.' % model)

And this on my page

The model being added to the query must derive from Model.

If I visit /search/q=Microsoft, it works fine. Is there another way to accomplish this?

Thanks for any pointers -Jay

Upvotes: 2

Views: 2674

Answers (1)

bennylope
bennylope

Reputation: 1163

There are a couple of things going on here. In your __call__ method you're assigning a category based on a string in the URL. In this error:

UserWarning: The model u'Vendor' is not registered for search

Note the unicode string. If you got an error like The model <class 'mymodel.Model'> is not registered for search then you'd know that you haven't properly created an index for that model. However this is a string, not a model! The models method on the SearchQuerySet class requires a class instance, not a string.

The first thing you could do is use that string to look up a model by content type. This is probably not a good idea! Even if you don't have models indexed which you'd like to keep away from prying eyes, you could at least generate some unnecessary errors.

Better to use a lookup in your view to route the query to the correct model index, using conditionals or perhaps a dictionary. In your __call__ method:

self.category = category.lower()

And if you have several models:

my_querysets = {
    'model1': SearchQuerySet().models(Model1),
    'model2': SearchQuerySet().models(Model2),
    'model3': SearchQuerySet().models(Model3),
}
# Default queryset then searches everything
kwargs['searchqueryset'] = my_querysets.get(self.category, SearchQuerySet())

Upvotes: 1

Related Questions