Ticket #2707: patch4.diff

File patch4.diff, 7.0 KB (added by sdm@…, 8 years ago)
  • django/contrib/search/base.py

     
    2727    # FIXME: This whole function is either silly or clever...
    2828    objPath = string.split('.')
    2929    model = None
    30 
    3130    if namespace is None:
    3231        # FIXME: This uses the sys._getframe hack to get the caller's namespace.
    3332        obj = sys._getframe(1).f_globals
     
    7069    # but sure makes things like this harder. Hopefully setting this attribute
    7170    # won't mess anything up...
    7271    obj._model = model
     72       
    7373    return obj
    7474
    75 
     75class PseudoField(str):
     76    """Dirty class used to generete a pseudo-field with the "name" attribute"""
     77    def __init__(self,name):
     78        self.name = name.split('.')[1]
     79    def upper(self):
     80        return self.name.upper()
     81   
    7682class Indexer(object):
    7783    def __init__(self, path, model, fields=None, attributes=None, namespace=None, **kwargs):
    7884        """Initialize an Indexer whose index data is stored at `path`.
     
    137143
    138144        # FIXME: Detect duplicates, or user-knows-best?
    139145        if isinstance(field, basestring):
    140             field = str_to_field(field,  namespace)
     146            try:
     147                field = str_to_field(field,  namespace)
     148            except models.fields.FieldDoesNotExist:
     149                # TODO: How call the function here?
     150                # Follow the dirty solution
     151                field = PseudoField(field)
    141152
    142153        if name:
    143154            self.attr_fields[name] = field
  • django/contrib/search/lucene.py

     
    9393        for name, field in self.attr_fields.iteritems():
    9494            # FIXME: Assumes no Foreign Keys! Lame!
    9595            value = getattr(row, field.name)
     96            # If the field is a function, they should be called
     97            if callable(value):
     98                field_value = str(value())
     99            else:
     100                field_value = str(value)
     101           
    96102            document.add(PyLucene.Field(name, str(value),
    97103                                        PyLucene.Field.Store.YES,
    98104                                        PyLucene.Field.Index.TOKENIZED))
  • django/contrib/search/xapian.py

     
    44import xapwrap.document
    55from itertools import imap
    66
    7 from base import Indexer, ResultSet
     7from query import ResultSet, Hit
     8from base import Indexer
    89
    910# TODO: This is incomplete.
    1011
    1112class XapianIndexer(Indexer):
    1213    def update(self, documents=None):
    13         idx = xapwrap.index.Index(self.path, True)
     14        idx = xapwrap.index.SmartIndex(self.path, True)
    1415
    1516        if documents is None:
    1617            update_queue = self.model.objects.all()
    1718        else:
    1819            update_queue = documents
    1920
    20         for row in documents:
     21        for row in update_queue:
    2122            keys = []
     23            text_fields = []
     24            keywords = []
    2225            for name, field in self.attr_fields.iteritems():
    23                 keys.append(xapwrap.document.SortKey(name, getattr(self.model, field.name)))
     26                # Get the field value based in the field name
     27                field_value = getattr(row, field.name)
     28                if callable(field_value):
     29                    field_value = str(field_value())
     30                else:
     31                    field_value = str(field_value)
     32               
     33                # Keys used for sort
     34                keys.append(xapwrap.document.SortKey(name, field_value))
    2435
    25             d = xapwrap.document.Document(textFields=fields, sortFields=keys, uid=row._get_pk_val())
     36                # Text used for order_by
     37                text_fields.append(xapwrap.document.TextField(name,field_value))
     38                text_fields.append(xapwrap.document.TextField(name,field_value,True))
     39            d = xapwrap.document.Document(
     40                                            textFields=text_fields,
     41                                            sortFields=keys,
     42                                            uid=row._get_pk_val(),
     43                                         )
    2644            idx.index(d)
     45           
    2746        idx.close()
    2847
    2948    def search(self, query, order_by='RELEVANCE'):
    30         idx = Index(self.path)
     49        idx = xapwrap.index.SmartIndex(self.path)
     50        prefixMap = {}
     51        for name, field in self.attr_fields.iteritems():
     52            prefixMap[name] = name
     53        idx.configure(prefixMap=prefixMap)
     54       
     55       
    3156        if order_by == 'RELEVANCE':
    3257            results = idx.search(query, sortByRelevence=True)
    3358        else:
     
    3661                ascending = False
    3762            while order_by[0] in '+-':
    3863                order_by = order_by[1:]
     64           
    3965            results = idx.search(query, order_by, sortAscending=ascending)
    40         return XapianResultSet(results)
     66        return XapianResultSet(results,self)
    4167
    4268
    4369class XapianResultSet(ResultSet):
     
    4975        return len(self._hits)
    5076
    5177    def __iter__(self):
    52         for hit in self._hits):
    53             yield XapianHit(hit, self._indexer)
     78        for hit in self._hits:
     79            yield XapianHit(hit,self._indexer)
    5480
     81    def __getitem__(self,pos):
     82        '''Allow use index-based access'''
     83        return XapianHit(self._hits[pos],self._indexer)
     84       
     85    def __getslice__(self,start,end):
     86        '''Allows use slices to retrive the information
     87        WARNING: This returns a generator, not a "list"
     88        '''
     89        for hit in self._hits[start:end]:
     90            yield XapianHit(hit,self._indexer)
    5591
    56 class XapianHit(object):
     92class XapianHit(Hit):
    5793    def get_pk(self):
    58         return self.data['pk']
     94        # FIXME: Hardcoded 'pk' field.
     95        return self.data['uid']
    5996
     97    def __getitem__(self, item):
     98        return self.data.__getitem__(item)
     99
    60100    def get_score(self):
    61101        return self.data['score']
    62102
  • django/contrib/search/query.py

     
    1010    def __len__(self):
    1111        raise NotImplementedError
    1212
    13     def __getitem__(self):
     13    def __getitem__(self,pos):
    1414        raise NotImplementedError
    1515
    1616
     
    2929
    3030    def get_pk(self):
    3131        raise NotImplementedError
     32   
     33    def get_object(self):
     34        return self.model.objects.get(pk=self.get_pk())
    3235
    3336    def __repr__(self):
    34         return "<%s: %s %s, Score: %s>" % (self.__class__.__name__,
     37        return "<%s: Model:%s pk:%s, Score:%s>" % (self.__class__.__name__,
    3538                                           self.model._meta,
    3639                                           self.get_pk(), self.score)
     40 No newline at end of file
Back to Top