Google 映射 API 版本 3.35 在 django 表单字段小部件中的问题

Google maps API issue with version 3.35 in a django form field widget

我在将 Google 地图 API 升级到版本 3.35 后遇到问题。目标是以一种形式显示地图,以便用户可以定义地理位置。我正在使用 Django 1.11.12 和 CanJS 2.0.2。

这是代码(为简单起见减少了),它适用于 Google 地图 API 版本 3.34,但不适用于版本 3.35。

models.py

from django.db import models
from maps.models import JSONField

class Institution(models.Model):
    geolocation = JSONField(blank=True, null=True)

maps/models.py

from django.db import models
from maps.forms import LatLngWidget

class JSONField(models.TextField):
    def formfield(self, **kwargs):
        kwargs.update({'widget': LatLngWidget()})
        return super(JSONField, self).formfield(**kwargs)

maps/forms.py

from django import forms
from django.conf import settings
from django.contrib.staticfiles.templatetags.staticfiles import static
from django.utils.safestring import mark_safe
from django.template.loader import render_to_string
from django.forms.widgets import Widget

class LatLngWidget(Widget):
    def __init__(self, attrs=None):
        super(LatLngWidget, self).__init__(attrs)
        self.width = 640
        self.height = 480

    def render(self, name, value, attrs=None):
        data = dict(name=name, value=value, width=self.width, height=self.height)
        html = render_to_string("maps/widget.html", data)
        return mark_safe(html)

    def _media(self):
        return forms.Media(css={"all": [static("maps/css/gmap.css"),],},)

    media = property(_media)

widget.html

<div class="map-container" id="geolocation-container">
<div class="map-box">
    <div class="map map-canvas" id="gmap-geolocation"></div>
</div>
</div>

<script src="https://maps.googleapis.com/maps/api/js?v=3.35&key=xxx"></script>

<script type="text/javascript">
    Map = can.Control({
        init: function(el, options) {
            this.map = null;
            this.marker = null;

            this.name = options.name;
            this.lat = options.lat || 0;
            this.lng = options.lng || 0;
            this.zoom = options.zoom || 2;

            this.createMap();
        },

        createMap: function() {
            var data = {
                'name': this.options.name,
                'width': this.options.width,
                'height': this.options.height,
                'lat': this.lat,
                'lng': this.lng,
                'zoom': this.zoom
            };

            var mapOptions = {
                zoom: 5,
                center: {lat: -25.344, lng: 131.036},
            };

            var target = 'gmap-'+this.name;
            console.log(target);

            this.map = new google.maps.Map(document.getElementById(target), mapOptions);
            // This code works with 3.34. Initial map is rendered with 3.35, but without buttons and not updated if zooming.
            // 3.34
            // > gmap-geolocation
            // 3.35
            // > gmap-geolocation
            // > gmap-undefined
            // > Uncaught TypeError: Cannot read property 'firstChild' of null js?v=3.35&key=xxx:70
            // > gmap-undefined

            //this.map = new google.maps.Map(document.getElementById('gmap-geolocation'), mapOptions);
            // This code works with 3.34. This code does not work at all with 3.35 - browser freezes.
        },
    });

    {% autoescape off %}
    var data = {% firstof value "{}" %};
    {% endautoescape %}
    data.name = "{{ name }}";
    data.width = "{{ width }}";
    data.height = "{{ height }}";
    new Map($("#geolocation-container"), data);
</script>

edit.html

<form method="post" action="" enctype="multipart/form-data">
   {% csrf_token %}
   {% formrow form.geolocation %}
</form>

问题似乎出在 widget.html。再一次,如果整个代码保持不变,只有 Google 映射 API 从 3.34 升级到 3.35,我会得到错误 "Uncaught TypeError: Cannot read property 'firstChild' of null".

如果有任何解决此问题的提示,我将不胜感激。

已通过重命名 CanJS 控制函数 "Map" 解决了该问题。 如果在 widget.html

Map = can.Control({

改为

Map2 = can.Control({

... 以及使用

创建的实例
new Map2($("#geolocation-container"), data);

... 然后使用 Google 地图 javascript API v3.35.

一切正常