0

由于 django 的应用程序,即智能选择,我遇到了麻烦,它尝试自行加载 jquery。我已经自己在头脑中加载 jquery,然后我正在加载与 JQuery UI 相关的东西。但是随着 smartselect 进入正文,它还会再次加载 jquery,这会导致 UI 相关内容出现问题。我不明白如果已经加载了 smartselect jquery,我该如何停止它。

以下是智能选择应用程序的 widgets.py 文件的代码。

    import django
from django.conf import settings
from django.forms.widgets import Select
from django.contrib.admin.templatetags.admin_static import static
from django.core.urlresolvers import reverse
from django.utils.encoding import iri_to_uri
from django.utils.safestring import mark_safe
from django.db.models import get_model
import locale
from smart_selects.utils import unicode_sorter


if django.VERSION >= (1, 2, 0) and getattr(settings,
        'USE_DJANGO_JQUERY', True):
    USE_DJANGO_JQUERY = True
else:
    USE_DJANGO_JQUERY = False
    JQUERY_URL = getattr(settings, 'JQUERY_URL', 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js')


class ChainedSelect(Select):
    def __init__(self, app_name, model_name, chain_field, model_field, show_all, auto_choose, manager=None, *args, **kwargs):
        self.app_name = app_name
        self.model_name = model_name
        self.chain_field = chain_field
        self.model_field = model_field
        self.show_all = show_all
        self.auto_choose = auto_choose
        self.manager = manager
        super(Select, self).__init__(*args, **kwargs)

    class Media:
        if USE_DJANGO_JQUERY:
            js = [static('admin/%s' % i) for i in
                  ('js/jquery.min.js', 'js/jquery.init.js')]
        elif JQUERY_URL:
            js = (
                JQUERY_URL,
            )

    def render(self, name, value, attrs=None, choices=()):
        if len(name.split('-')) > 1: # formset
            chain_field = '-'.join(name.split('-')[:-1] + [self.chain_field])
        else:
            chain_field = self.chain_field

        if self.show_all:
            view_name = "chained_filter_all"
        else:
            view_name = "chained_filter"
        kwargs = {'app':self.app_name, 'model':self.model_name, 'field':self.model_field, 'value':"1"}
        if self.manager is not None:
            kwargs.update({'manager': self.manager})
        url = "/".join(reverse(view_name, kwargs=kwargs).split("/")[:-2])
        if self.auto_choose:
            auto_choose = 'true'
        else:
            auto_choose = 'false'
        empty_label = iter(self.choices).next()[1] # Hacky way to getting the correct empty_label from the field instead of a hardcoded '--------'
        js = """
        <script type="text/javascript">
        //<![CDATA[
        (function($) {
            function fireEvent(element,event){
                if (document.createEventObject){
                // dispatch for IE
                var evt = document.createEventObject();
                return element.fireEvent('on'+event,evt)
                }
                else{
                // dispatch for firefox + others
                var evt = document.createEvent("HTMLEvents");
                evt.initEvent(event, true, true ); // event type,bubbling,cancelable
                return !element.dispatchEvent(evt);
                }
            }

            function dismissRelatedLookupPopup(win, chosenId) {
                var name = windowname_to_id(win.name);
                var elem = document.getElementById(name);
                if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
                    elem.value += ',' + chosenId;
                } else {
                    elem.value = chosenId;
                }
                fireEvent(elem, 'change');
                win.close();
            }

            $(document).ready(function(){
                function fill_field(val, init_value){
                    if (!val || val==''){
                        options = '<option value="">%(empty_label)s<'+'/option>';
                        $("#%(id)s").html(options);
                        $('#%(id)s option:first').attr('selected', 'selected');
                        $("#%(id)s").trigger('change');
                        return;
                    }
                    $.getJSON("%(url)s/"+val+"/", function(j){
                        var options = '<option value="">%(empty_label)s<'+'/option>';
                        for (var i = 0; i < j.length; i++) {
                            options += '<option value="' + j[i].value + '">' + j[i].display + '<'+'/option>';
                        }
                        var width = $("#%(id)s").outerWidth();
                        $("#%(id)s").html(options);
                        if (navigator.appVersion.indexOf("MSIE") != -1)
                            $("#%(id)s").width(width + 'px');
                        $('#%(id)s option:first').attr('selected', 'selected');
                        var auto_choose = %(auto_choose)s;
                        if(init_value){
                            $('#%(id)s option[value="'+ init_value +'"]').attr('selected', 'selected');
                        }
                        if(auto_choose && j.length == 1){
                            $('#%(id)s option[value="'+ j[0].value +'"]').attr('selected', 'selected');
                        }
                        $("#%(id)s").trigger('change');
                    })
                }

                if(!$("#id_%(chainfield)s").hasClass("chained")){
                    var val = $("#id_%(chainfield)s").val();
                    fill_field(val, "%(value)s");
                }

                $("#id_%(chainfield)s").change(function(){
                    var start_value = $("#%(id)s").val();
                    var val = $(this).val();
                    fill_field(val, start_value);
                })
            })

            dismissAddAnotherPopup = function(win, newId, newRepr) {
                oldDismissAddAnotherPopup(win, newId, newRepr);
                if (windowname_to_id(win.name) == "id_%(chainfield)s") {
                    $("#id_%(chainfield)s").change();
                }
            }
            var oldDismissAddAnotherPopup = dismissAddAnotherPopup;
        })(jQuery || django.jQuery);
        //]]>
        </script>

        """ % {"chainfield":chain_field, "url":url, "id":attrs['id'], 'value':value, 'auto_choose':auto_choose, 'empty_label': empty_label}
        final_choices = []

        if value:
            item = self.queryset.filter(pk=value)[0]
            try:
                pk = getattr(item, self.model_field + "_id")
                filter = {self.model_field:pk}
            except AttributeError:
                try: # maybe m2m?
                    pks = getattr(item, self.model_field).all().values_list('pk', flat=True)
                    filter = {self.model_field + "__in":pks}
                except AttributeError:
                    try: # maybe a set?
                        pks = getattr(item, self.model_field + "_set").all().values_list('pk', flat=True)
                        filter = {self.model_field + "__in":pks}
                    except: # give up
                        filter = {}
            filtered = list(get_model(self.app_name, self.model_name).objects.filter(**filter).distinct())
            filtered.sort(cmp=locale.strcoll, key=lambda x:unicode_sorter(unicode(x)))
            for choice in filtered:
                final_choices.append((choice.pk, unicode(choice)))
        if len(final_choices) > 1:
            final_choices = [("", (empty_label))] + final_choices
        if self.show_all:
            final_choices.append(("", (empty_label)))
            self.choices = list(self.choices)
            self.choices.sort(cmp=locale.strcoll, key=lambda x:unicode_sorter(x[1]))
            for ch in self.choices:
                if not ch in final_choices:
                    final_choices.append(ch)
        self.choices = ()
        final_attrs = self.build_attrs(attrs, name=name)
        if 'class' in final_attrs:
            final_attrs['class'] += ' chained'
        else:
            final_attrs['class'] = 'chained'
        output = super(ChainedSelect, self).render(name, value, final_attrs, choices=final_choices)
        output += js
        return mark_safe(output)

D 我知道如何检查 jquery 是否已经加载到 JS 中。但是Django如何处理它,不知道。有时我认为这些东西仍然有效,但有时不行。不明白为什么会这样。以上是我在未定义$('.datepicker').datepicker()并通过萤火虫检查后得出的结论。有时这段代码也不会引起问题。我不明白为什么。

请告诉你们是否有任何想法。请问我是否不够清楚。

谢谢


更新

这是我加载 jquery 和 jquery ui 的方式:

    <!DOCTYPE html>
<html class="no-js" lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Kaasib.com</title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width">
  <link rel="stylesheet" href="{{STATIC_URL}}css/style.css" />
  <link rel="stylesheet" href="{{STATIC_URL}}css/ui-lightness/jquery-ui-1.8.23.custom.css" />
  <script src="{{STATIC_URL}}js/libs/jquery-1.7.1.min.js"></script>
  <script src="{{STATIC_URL}}js/libs/jquery-ui-1.8.23.custom.min.js "></script>

  <script src="{{STATIC_URL}}js/main.js"></script>
</head> 
4

1 回答 1

0

好的,问题出在我的最后,我遇到了错误, Error: ReferenceError: dismissAddAnotherPopup is not defined Source File: http://localhost:8000/jobs/create Line: 195

所以我通过将这var oldDismissAddAnotherPopup = dismissAddAnotherPopup;一行放在dismissAddAnotherPopup()函数定义之后来解决这个问题。不知道为什么,但它开始产生问题,所以我再次遇到那个 js 错误,但现在我的代码正在运行并且它正在显示 datepicker。

我的模板文件中还有一些代码再次加载 jquery。很抱歉,这是我自己的错,因为我使用 HTML5 样板有点错误。因此,对于这个问题的 yu 来说,唯一的好信息是首先正确检查某些东西的用法,然后再使用它。

于 2012-09-14T22:07:04.333 回答