Index: django/contrib/search/base.py
===================================================================
--- django/contrib/search/base.py	(revision 3754)
+++ django/contrib/search/base.py	(working copy)
@@ -27,7 +27,6 @@
     # FIXME: This whole function is either silly or clever...
     objPath = string.split('.')
     model = None
-
     if namespace is None:
         # FIXME: This uses the sys._getframe hack to get the caller's namespace.
         obj = sys._getframe(1).f_globals
@@ -70,9 +69,16 @@
     # but sure makes things like this harder. Hopefully setting this attribute
     # won't mess anything up...
     obj._model = model
+        
     return obj
 
-
+class PseudoField(str):
+    """Dirty class used to generete a pseudo-field with the "name" attribute"""
+    def __init__(self,name):
+        self.name = name.split('.')[1]
+    def upper(self):
+        return self.name.upper()
+    
 class Indexer(object):
     def __init__(self, path, model, fields=None, attributes=None, namespace=None, **kwargs):
         """Initialize an Indexer whose index data is stored at `path`.
@@ -137,7 +143,12 @@
 
         # FIXME: Detect duplicates, or user-knows-best?
         if isinstance(field, basestring):
-            field = str_to_field(field,  namespace)
+            try:
+                field = str_to_field(field,  namespace)
+            except models.fields.FieldDoesNotExist:
+                # TODO: How call the function here?
+                # Follow the dirty solution
+                field = PseudoField(field)
 
         if name:
             self.attr_fields[name] = field
Index: django/contrib/search/lucene.py
===================================================================
--- django/contrib/search/lucene.py	(revision 3754)
+++ django/contrib/search/lucene.py	(working copy)
@@ -93,6 +93,12 @@
         for name, field in self.attr_fields.iteritems():
             # FIXME: Assumes no Foreign Keys! Lame!
             value = getattr(row, field.name)
+            # If the field is a function, they should be called
+            if callable(value):
+                field_value = str(value())
+            else:
+                field_value = str(value)
+            
             document.add(PyLucene.Field(name, str(value),
                                         PyLucene.Field.Store.YES,
                                         PyLucene.Field.Index.TOKENIZED))
Index: django/contrib/search/xapian.py
===================================================================
--- django/contrib/search/xapian.py	(revision 3754)
+++ django/contrib/search/xapian.py	(working copy)
@@ -4,30 +4,45 @@
 import xapwrap.document
 from itertools import imap
 
-from base import Indexer, ResultSet
+from query import ResultSet, Hit
+from base import Indexer
 
 # TODO: This is incomplete.
 
 class XapianIndexer(Indexer):
     def update(self, documents=None):
-        idx = xapwrap.index.Index(self.path, True)
+        idx = xapwrap.index.SmartIndex(self.path, True)
 
         if documents is None:
             update_queue = self.model.objects.all()
         else:
             update_queue = documents
 
-        for row in documents:
+        for row in update_queue:
             keys = []
+            text_fields = []
+            prefixes = {}
             for name, field in self.attr_fields.iteritems():
-                keys.append(xapwrap.document.SortKey(name, getattr(self.model, field.name)))
+                # Get the field value based in the field name
+                field_value = getattr(row, field.name)
+                if callable(field_value):
+                    field_value = str(field_value())
+                else:
+                    field_value = str(field_value)
+                
+                # Keys used for sort
+                keys.append(xapwrap.document.SortKey(name, field_value))
 
-            d = xapwrap.document.Document(textFields=fields, sortFields=keys, uid=row._get_pk_val())
+                # Text used for order_by
+                text_fields.append(xapwrap.document.TextField(name,field_value))
+            d = xapwrap.document.Document(textFields=text_fields,sortFields=keys, uid=row._get_pk_val())
+            idx.configure(prefixMap=prefixes)
             idx.index(d)
+            
         idx.close()
 
     def search(self, query, order_by='RELEVANCE'):
-        idx = Index(self.path)
+        idx = xapwrap.index.SmartIndex(self.path)
         if order_by == 'RELEVANCE':
             results = idx.search(query, sortByRelevence=True)
         else:
@@ -36,8 +51,9 @@
                 ascending = False
             while order_by[0] in '+-':
                 order_by = order_by[1:]
+                
             results = idx.search(query, order_by, sortAscending=ascending)
-        return XapianResultSet(results)
+        return XapianResultSet(results,self)
 
 
 class XapianResultSet(ResultSet):
@@ -49,16 +65,19 @@
         return len(self._hits)
 
     def __iter__(self):
-        for hit in self._hits):
-            yield XapianHit(hit, self._indexer)
+        for hit in self._hits:
+            yield XapianHit(hit,self._indexer)
 
 
-class XapianHit(object):
+class XapianHit(Hit):
     def get_pk(self):
-        return self.data['pk']
+        # FIXME: Hardcoded 'pk' field.
+        return self.data['uid']
 
+    def __getitem__(self, item):
+        return self.data.__getitem__(item)
+
     def get_score(self):
         return self.data['score']
 
     score = property(get_score)
-
Index: django/contrib/search/query.py
===================================================================
--- django/contrib/search/query.py	(revision 3754)
+++ django/contrib/search/query.py	(working copy)
@@ -29,8 +29,11 @@
 
     def get_pk(self):
         raise NotImplementedError
+    
+    def get_object(self):
+        return self.model.objects.get(pk=self.get_pk())
 
     def __repr__(self):
-        return "<%s: %s %s, Score: %s>" % (self.__class__.__name__,
+        return "<%s: Model:%s pk:%s, Score:%s>" % (self.__class__.__name__,
                                            self.model._meta,
                                            self.get_pk(), self.score)
\ No newline at end of file
