import pickle

from django.forms.widgets import Widget
from django.utils.safestring import mark_safe
from django.db.models.query import QuerySet
from django.core.urlresolvers import reverse

from simple_autocomplete.monkey import _simple_autocomplete_queryset_cache
from simple_autocomplete.utils import get_search_fieldname

class AutoCompleteWidget(Widget):
    input_type = 'autocomplete'
    url = None
    initial_display = None
    token = None
    model = None

    def __init__(self, url=None, initial_display=None, token=None, model=None, *args, **kwargs):
        """
        url: a custom URL that returns JSON with format [(value, label),(value,
        label),...].  

        initial_display: if url is provided then initial_display is the initial
        content of the autocomplete box, eg. "John Smith".

        token: an identifier to retrieve a cached queryset. Used internally.

        model: the model that the queryset objects are instances of. Used
        internally.
        """
        self.url = url
        self.initial_display = initial_display
        self.token = token
        self.model = model
        super(AutoCompleteWidget, self).__init__(*args, **kwargs)

    def render(self, name, value, attrs=None):
        if value is None:
            value = ''
      
        display = ''
        if self.url:
            url = self.url
            display = self.initial_display

        else:
            fieldname = get_search_fieldname(self.model)
            url = reverse('simple-autocomplete', args=[self.token])
            if value:            
                dc, dc, query = pickle.loads(_simple_autocomplete_queryset_cache[self.token])
                queryset = QuerySet(model=self.model, query=query)
                display = getattr(queryset.get(pk=value), fieldname)

        html = """
    <script type="text/javascript">
    $(document).ready(function(){

    $("#id_%s_helper").autocomplete({
        source: function(request, response){
            $.ajax({
                url: "%s",
                data: {q: request.term},
                success: function(data) {
                    if (data != 'CACHE_MISS')                    
                        response($.map(data, function(item) {
                            return {
                                label: item[1],
                                value: item[1],
                                real_value: item[0]
                            };
                        }));
                },
                dataType: "json"
            });
        },
        select: function(event, ui) { $('#id_%s').val(ui.item.real_value); },
        minLength: 3
    });

    });
    </script>

<input id="id_%s_helper" type="text" value="%s" />
<input name="%s" id="id_%s" type="hidden" value="%s" />""" % (name, url, name, name, display, name, name, value)
        return mark_safe(html)

    def value_from_datadict(self, data, files, name):
        return data.get(name, None)

@@ -41,21 +41,21 @@
  import 
-Widge
+Selec
 t%0Afrom d
@@ -344,21 +344,21 @@
 eWidget(
-Widge
+Selec
 t):%0A    
@@ -1436,142 +1436,343 @@
     
-fieldname = get_search_fieldname(self.model)%0A            url = reverse('simple-autocomplete', args=%5Bself.token%5D)%0A            if value:
+dc, dc, query = pickle.loads(_simple_autocomplete_queryset_cache%5Bself.token%5D)%0A            queryset = QuerySet(model=self.model, query=query)%0A            if queryset.count() %3C 30:%0A                # Render the normal select widget if size below threshold%0A                return super(AutoCompleteWidget, self).render(name, value, attrs)%0A
     
@@ -1771,32 +1771,37 @@
 rs)%0A            
+else:
 %0A               
@@ -1805,45 +1805,30 @@
     
-dc, dc, query = pickle.loads(_
+url = reverse('
 simple
-_
+-
 auto
@@ -1831,39 +1831,32 @@
 autocomplete
-_queryset_cache
+', args=
 %5Bself.token%5D
@@ -1877,59 +1877,107 @@
     
-queryset = QuerySet(model=self.model, query=query)%0A
+fieldname = get_search_fieldname(self.model)            %0A                if value:            %0A    
     
@@ -2042,16 +2042,20 @@
 dname)%0A%0A
+    
         
@@ -3097,16 +3097,20 @@
  value)%0A
+    
         

Make widget flexible. If vocab below certain threshold then revert to normal select widget.