source: main/branches/3D/openPLM/plmapp/search_indexes.py @ 662

Revision 662, 4.8 KB checked in by pcosquer, 9 years ago (diff)

3D branch: merge changes from trunk (rev [661])

Line 
1from django.conf import settings
2from django.db.models import signals
3from django.db.models.loading import get_model
4
5from haystack import site
6from haystack import indexes
7from haystack.indexes import *
8from haystack.models import SearchResult
9
10import openPLM.plmapp.models as models
11from openPLM.plmapp.tasks import update_index
12
13# just a hack to prevent a KeyError
14def get_state(self):
15    ret_dict = self.__dict__.copy()
16    if 'searchsite' in ret_dict:
17        del(ret_dict['searchsite'])
18    del(ret_dict['log'])
19    return ret_dict
20SearchResult.__getstate__ = get_state
21
22###########################
23# from https://github.com/mixcloud/django-celery-haystack-SearchIndex/
24# by sdcooke
25
26def remove_instance_from_index(instance):
27    model_class = get_model(instance._meta.app_label, instance._meta.module_name)
28    search_index = site.get_index(model_class)
29    search_index.remove_object(instance)
30
31class QueuedSearchIndex(indexes.SearchIndex):
32    """
33A ``SearchIndex`` subclass that enqueues updates for later processing.
34
35Deletes are handled instantly since a reference, not the instance, is put on the queue. It would not be hard
36to update this to handle deletes as well (with a delete task).
37"""
38    # We override the built-in _setup_* methods to connect the enqueuing operation.
39    def _setup_save(self, model):
40        signals.post_save.connect(self.enqueue_save, sender=model)
41
42    def _setup_delete(self, model):
43        signals.post_delete.connect(self.enqueue_delete, sender=model)
44
45    def _teardown_save(self, model):
46        signals.post_save.disconnect(self.enqueue_save, sender=model)
47
48    def _teardown_delete(self, model):
49        signals.post_delete.disconnect(self.enqueue_delete, sender=model)
50
51    def enqueue_save(self, instance, **kwargs):
52        if not getattr(instance, "no_index", False):
53            update_index.delay(instance._meta.app_label,
54                    instance._meta.module_name, instance._get_pk_val())
55
56    def enqueue_delete(self, instance, **kwargs):
57        remove_instance_from_index(instance)
58
59##################
60
61def set_template_name(index):
62    for name, field in index.fields.iteritems():
63        field.template_name = "search/indexes_%s.txt" % name
64
65
66class QueuedModelSearchIndex(ModelSearchIndex, QueuedSearchIndex):
67    pass
68
69class UserIndex(ModelSearchIndex):
70    class Meta:
71        pass
72   
73    rendered = CharField(use_template=True, indexed=False)
74    rendered_add = CharField(use_template=True, indexed=False)
75
76set_template_name(UserIndex)
77site.register(models.User, UserIndex)
78
79class GroupIndex(ModelSearchIndex):
80    class Meta:
81        pass
82   
83    rendered = CharField(use_template=True, indexed=False)
84    rendered_add = CharField(use_template=True, indexed=False)
85
86set_template_name(GroupIndex)
87site.register(models.GroupInfo, GroupIndex)
88
89
90
91for key, model in models.get_all_plmobjects().iteritems():
92    if model == models.GroupInfo:
93        continue
94    class ModelIndex(QueuedModelSearchIndex):
95        model = model
96        key = key
97        class Meta:
98            fields = set(model.get_creation_fields())
99            fields.update(model.get_modification_fields())
100       
101        owner = CharField(model_attr="owner")
102        creator = CharField(model_attr="creator")
103        state = CharField(model_attr="state__name")
104        lifecycle = CharField(model_attr="lifecycle__name")
105
106        rendered = CharField(use_template=True, indexed=False)
107        rendered_add = CharField(use_template=True, indexed=False)
108       
109        def prepare_owner(self, obj):
110            return obj.owner.username
111
112        def prepare_creator(self, obj):
113            return obj.creator.username
114
115        def index_queryset(self):
116            if "type" in self.model.get_creation_fields():
117                return self.model.objects.filter(type=self.key)
118            else:
119                return self.model.objects.all()
120    set_template_name(ModelIndex)
121    site.register(model, ModelIndex)
122
123from subprocess import Popen, PIPE
124import codecs
125import os.path
126text_files = set((".txt",))
127
128class DocumentFileIndex(QueuedModelSearchIndex):
129    text = CharField(document=True, use_template=True)
130    filename = CharField(model_attr='filename')
131    file = CharField(model_attr='file')
132   
133    rendered = CharField(use_template=True, indexed=False)
134    rendered_add = CharField(use_template=True, indexed=False)
135
136    def prepare_file(self, obj):
137        # if it is a text file, we can dump it
138        # it's faster than launching a new process
139        path = obj.file.path
140        name, ext = os.path.splitext(path)
141        if ext.lower() in text_files:
142            return codecs.open(path, encoding="utf-8", errors="ignore").read()
143        else:
144            p = Popen([settings.EXTRACTOR, path], stdout=PIPE, close_fds=True)
145            return p.stdout.read()
146
147site.register(models.DocumentFile, DocumentFileIndex)
148
Note: See TracBrowser for help on using the repository browser.