etianen / django-watson

Full-text multi-table search application for Django. Easy to install and use, with good performance.
BSD 3-Clause "New" or "Revised" License
1.2k stars 130 forks source link

Accessing stored fields on proxy models fails #160

Open ryanmrubin opened 8 years ago

ryanmrubin commented 8 years ago

I'm running django-watson 1.2.1 with django 1.8.12. I have a model setup that involves a few proxies for different product types which are all stored on the same Product table. I've registered the proxies separately with watson:

# apps.py
        ...
        Book = self.get_model('Book')
        book_qs = Book.search_types.searchable()
        watson.register(book_qs, ProductSearchAdapter)

        BibleSearch = self.get_model('BibleSearch')
        bible_qs = BibleSearch.objects.all_current()
        watson.register(bible_qs, ProductSearchAdapter)
        # etc

This works fine for most things, except when I try to access any stored fields, when it tries to deserialize the meta based on the root model, not based on the proxy, and throws an error because that root model is not registered with Watson:

  ...
  File "/opt/env/crossway-website/local/lib/python2.7/site-packages/watson/models.py", line 89, in meta
    meta_value = self._deserialize_meta()
  File "/opt/env/crossway-website/local/lib/python2.7/site-packages/watson/models.py", line 79, in _deserialize_meta
    adapter = engine.get_adapter(model)
  File "/opt/env/crossway-website/local/lib/python2.7/site-packages/watson/search.py", line 421, in get_adapter
    model = model,
RegistrationError: <class 'crosswayshop.models.Product'> is not registered with this search engine
[07/Apr/2016 13:23:42] "GET /search/?q=love HTTP/1.0" 500 36608

Now, the problem is solved if I register an empty queryset from the Product model so that it knows how to deserialize the meta, but that doesn't seem like an ideal solution:

        Product = self.get_model('Product')
        product_qs = Product.objects.none()
        watson.register(product_qs, ProductSearchAdapter)
etianen commented 8 years ago

I'm afraid I'm away at the moment, but will have a look when I'm back next week.

On Thu, 7 Apr 2016 at 20:03 Ryan Rubin notifications@github.com wrote:

I'm running django-watson 1.2.1 with django 1.8.12. I have a model setup that involves a few proxies for different product types which are all stored on the same Product table. I've registered the proxies separately with watson:

    Book = self.get_model('Book')
    book_qs = Book.search_types.searchable()
    watson.register(book_qs, ProductSearchAdapter)

    BibleSearch = self.get_model('BibleSearch')
    bible_qs = BibleSearch.objects.all_current()
    watson.register(bible_qs, ProductSearchAdapter)
    # etc

This works fine for most things, except when I try to access any stored fields, when it tries to deserialize the meta based on the root model, not based on the proxy, and throws an error because that root model is not registered with Watson:

... File "/opt/env/crossway-website/local/lib/python2.7/site-packages/watson/models.py", line 89, in meta meta_value = self._deserialize_meta() File "/opt/env/crossway-website/local/lib/python2.7/site-packages/watson/models.py", line 79, in _deserialize_meta adapter = engine.get_adapter(model) File "/opt/env/crossway-website/local/lib/python2.7/site-packages/watson/search.py", line 421, in get_adapter model = model, RegistrationError: <class 'crosswayshop.models.Product'> is not registered with this search engine [07/Apr/2016 13:23:42] "GET /search/?q=love HTTP/1.0" 500 36608

Now, the problem is solved if I register an empty queryset from the Product model so that it knows how to deserialize the meta, but that doesn't seem like an ideal solution:

    Product = self.get_model('Product')
    product_qs = Product.objects.none()
    watson.register(product_qs, ProductSearchAdapter)

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/etianen/django-watson/issues/160

etianen commented 8 years ago

Okay, it looks like django-watson doesn't support separate registration for proxy models. I guess it probably should.

There are a few changes that are needed:

  1. Adding a for_concrete_model=True argument to watson.register().
  2. Respect this flag in all ContentType.objects.get_for_model() calls in the codebase.

I'll take a pull request that implements this, if it's urgent.