Форма Django не будет отправлена ​​из-за поля виджета автозаполнения

Я хочу заполнить текстовый ввод в моей форме, используя виджет автозаполнения, который я создал с помощью jquery ui. Все работает именно так, как я хочу, кроме случаев, когда форма отправлена.

Проблема в том, что когда я отправляю форму, ввод текста автоматически сбрасывается (я не знаю почему), и после этого страница перезагружается, сообщая, что поле является обязательным (просто проверка работает так, как это должно). Конечно, если он не сбросит поле, все будет хорошо.

Я не знаю, если мое событие выбора автозаполнения работает нормально, вот код:

 select : function (e, ui) {
   // I create a new attribute to store de database primary key of this option. This is
   // usefull later on.
   $('#%(input_id)s').attr('itemid', ui.item.real_value);

   // I set the input text value's.
   $('#%(input_id)s').val(ui.item.label);
 }

Вот полный код автозаполнения:

class AutocompleteTextInputWidget (forms.TextInput):

  def media(self):
    js = ("/js/autocomplete.js", "pepe.js")

  def __init__(self, source, options={}, attrs={}):
    self.options = None
    self.attrs = {'autocomplete': 'off'}
    self.source = source
    self.minLength = 1
    self.delay = 0
    if len(options) > 0:
        self.options = JSONEncoder().encode(options)

    self.attrs.update(attrs)

  def render(self, name, value=None, attrs=None):
    final_attrs = self.build_attrs(attrs)        
    options = ''

    if value:
        final_attrs['value'] = escape(value)

    if isinstance(self.source, list) or isinstance(self.source, tuple):
        # Crea un Json con las opciones.
        source = '[' 
        for i in range(0, len(self.source)):
            if i > 0:
                source += ', '
            source += '"' + self.source[i] + '"'
        source += ']'

        options = u'''
            delay : %(delay)d,
            minLength : %(minlength)s,
            source : %(source)s
        '''  % {
               'delay' : self.delay,
               'minlength' : self.minLength,
               'source' : source
        }

    elif isinstance(self.source, str):
        options = u'''
            delay : %(delay)d,
            minLength : %(minlength)s,
            source : function (request, response) {
                if ($(this).data('xhr')) {
                    $(this).data('xhr').abort();
                }
                $(this).data('xhr', $.ajax({
                    url : "%(source_url)s",
                    dataType : "json",
                    data : {term : request.term},
                    beforeSend : function(xhr, settings) {
                        $('#%(input_id)s').removeAttr('itemid');
                    },
                    success : function(data) {
                        if (data != 'CACHE_MISS') {
                            response($.map(data, function(item) {
                                return {
                                    label : item[1],
                                    value: item[1],
                                    real_value : item[0]
                                };
                            }));
                        }
                    },
                }))
            },
            select : function (e, ui) {
                $('#%(input_id)s').attr('itemid', ui.item.real_value);
                $('#%(input_id)s').val(ui.item.label);
            }
        ''' % {
               'delay' : self.delay,
               'minlength' : self.delay,
               'source_url' : self.source,
               'input_id' : final_attrs['id'],
        }
    if not self.attrs.has_key('id'):
        final_attrs['id'] = 'id_%s' % name    

    return mark_safe(u''' 
        <input type="text" %(attrs)s/>
        <script type="text/javascript">
            $("#%(input_id)s").autocomplete({
               %(options)s 
            });
        </script>
    ''' % {
           'attrs' : flatatt(final_attrs),
           'options' :  options, 
           'input_id' : final_attrs['id']
    })

Подсказка: если я напишу какой-то текст, не выделив его из автозаполнения, он все равно потерпит неудачу.

Другой совет: если я установлю поле как необязательное, оно будет отображаться пустым.

Что я должен сделать, чтобы сделать эту работу, когда я отправляю форму??? Я часами пытался сделать эту работу. Как я могу заполнить форму, чтобы узнать, что я уже заполнил это поле?

Вот код формы:

test = forms.CharField(label = "autotest", widget = AutocompleteTextInputWidget('/myjsonservice'))

Это визуализированный HTML:

<input type="text"  autocomplete="off" id="id_test"/>
        <script type="text/javascript">
            $("#id_test").autocomplete({

            delay : 0,
            minLength : 0,
            source : function (request, response) {
                if ($(this).data('xhr')) {
                    $(this).data('xhr').abort();
                }
                $(this).data('xhr', $.ajax({
                    url : "/myjsonservice",
                    dataType : "json",
                    data : {term : request.term},
                    beforeSend : function(xhr, settings) {
                        $('#id_test').removeAttr('itemid');
                    },
                    success : function(data) {
                        if (data != 'CACHE_MISS') {
                            response($.map(data, function(item) {
                                return {
                                    label : item[1],
                                    value: item[1],
                                    real_value : item[0]
                                };
                            }));
                        }
                    },
                }))
            },
            select : function (e, ui) {
                $('#id_test').attr('itemid', ui.item.real_value);
                $('#id_test').val(ui.item.label);
            }

            });
        </script>

1 ответ

Решение

В конце концов нашел ответ, проблема была в том, что атрибут "name" не отображался. Следовательно, поле не может попасть в представление как часть запроса.

Окончательный код виджета автозаполнения закончился так:

class AutocompleteTextInputWidget (forms.TextInput):

    def media(self):
        js = ("/js/autocomplete.js", "pepe.js")

    def __init__(self, source, options={}, attrs={}):
        self.options = None
        self.attrs = {'autocomplete': 'off'}
        self.source = source
        self.minLength = 1
        self.delay = 0
        if len(options) > 0:
            self.options = JSONEncoder().encode(options)

        self.attrs.update(attrs)

    def render(self, name, value=None, attrs=None):
        final_attrs = self.build_attrs(attrs)       
        options = ''

        if value:
            final_attrs['value'] = escape(value)

        if isinstance(self.source, list) or isinstance(self.source, tuple):
            # Crea un Json con las opciones.
            source = '[' 
            for i in range(0, len(self.source)):
                if i > 0:
                    source += ', '
                source += '"' + self.source[i] + '"'
            source += ']'

            options = u'''
                delay : %(delay)d,
                minLength : %(minlength)s,
                source : %(source)s
            '''  % {
                   'delay' : self.delay,
                   'minlength' : self.minLength,
                   'source' : source
            }

        elif isinstance(self.source, str):
            options = u'''
                delay : %(delay)d,
                minLength : %(minlength)s,
                source : function (request, response) {
                    if ($(this).data('xhr')) {
                        $(this).data('xhr').abort();
                    }
                    $(this).data('xhr', $.ajax({
                        url : "%(source_url)s",
                        dataType : "json",
                        data : {term : request.term},
                        beforeSend : function(xhr, settings) {
                            $('#%(input_id)s').removeAttr('itemid');
                        },
                        success : function(data) {
                            if (data != 'CACHE_MISS') {
                                response($.map(data, function(item) {
                                    return {
                                        label : item[1],
                                        value: item[1],
                                        real_value : item[0]
                                    };
                                }));
                            }
                        },
                    }))
                },
                select : function (e, ui) {
                    $('#%(input_id)s').attr('itemid', ui.item.real_value);
                    $('#%(input_id)s').val(ui.item.label);
                }
            ''' % {
                   'delay' : self.delay,
                   'minlength' : self.delay,
                   'source_url' : self.source,
                   'input_id' : final_attrs['id'],
            }
        if not self.attrs.has_key('id'):
            final_attrs['id'] = 'id_%s' % name    

        return mark_safe(u''' 
            <input type="text" name="%(name)s" %(attrs)s/>
            <script type="text/javascript">
                $("#%(input_id)s").autocomplete({
                   %(options)s 
                });
            </script>
        ''' % {
               'attrs' : flatatt(final_attrs),
               'options' :  options, 
               'input_id' : final_attrs['id'],
               'name' : name
        })
  1. Если кто-то знает, как улучшить этот грязный код, было бы неплохо.
  2. Если кто-то знает о хорошей документации по виджетам для django 1.4 (кроме официальной, которая, кстати, отстой), это тоже было бы неплохо.

Пока все хорошо!

Другие вопросы по тегам