由于自动完成小部件字段,Django表单不会提交

时间:2012-07-24 23:29:24

标签: django jquery-ui django-forms django-widget

我想使用我使用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 个答案:

答案 0 :(得分:3)

终于找到了答案,问题是没有呈现“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的一个不错的小部件文档(除了官方的,这样很糟糕的话)它也会很好。
  3. 再见,好好编码每个人!!!