流块中的自定义字段面板性能

Custom field panel performance in stream block

我正在使用 wagtailgmaps 将 google 地图功能添加到我的项目中。用它 很简单,我想添加一个流块以供使用 Google Maps 块到 内容.

但是,我们有一个大问题,这个包只添加了一个新的edit_handler,它没有添加一个新的模型或字段,只为管理员添加一个新的处理程序。

所以,我的问题是,如何创建 Google Maps 流块添加 处理程序功能?

谢谢!

要创建一个新的StreamBlock,您是否需要为您的字段创建一个小部件:

 def render_form(self, value, prefix='', errors=None):
        widget = self.field.widget

        widget_attrs = {'id': prefix, 'placeholder': self.label}

        field_value = self.value_for_form(value)

        if hasattr(widget, 'render_with_errors'):
            widget_html = widget.render_with_errors(prefix, field_value, attrs=widget_attrs, errors=errors)
            widget_has_rendered_errors = True
        else:
            widget_html = widget.render(prefix, field_value, attrs=widget_attrs)
            widget_has_rendered_errors = False

        return render_to_string('wagtailadmin/block_forms/field.html', {
            'name': self.name,
            'classes': self.meta.classname,
            'widget': widget_html,
            'field': self.field,
            'errors': errors if (not widget_has_rendered_errors) else None
        })

一般情况下,base core中的所有block都有这个功能,使用widget就可以看到。

所以,首先我们必须为地图创建一个小部件:

class MapsField(HiddenInput):
    ***
    def __init__(self, *args, **kwargs):
        self.address_field = kwargs.pop('address_field', self.address_field)
        ***

        super(MapField, self).__init__(*args, **kwargs)

    class Media:
        css = {
            'all': ('*/**/geo-field.css',)
        }

        js = (
            '*/**/geo-field.js',
            'https://maps.google.com/maps/api/js?key={}&libraries=places'
            .format(
                GOOGLE_MAPS_V3_APIKEY
            ),
        )

    def render(self, name, value, attrs=None):
        out = super(MapField, self).render(name, value, attrs)

        location = format_html(
            '<div class="input">'
            '<input id="_id_{}_latlng" class="geo-field-location" maxlength="250" type="text">'  # NOQA
            '</div>',
            name
        )

        ***

        return mark_safe(
            '<script>window["{}"] = {};</script>'.format(data_id, json_data) +
            out +
            location +
            '<div class="geo-field" data-data-id="{}"></div>'.format(data_id) +
            """
            <script>
            (function(){
                if (document.readyState === 'complete') {
                    return initializeGeoFields();
                }
                $(window).load(function() {
                    initializeGeoFields();
                });
            })();
            </script>
            """
        )

现在,我们将创建一个扩展默认块的新块 wagtail block:from

from wagtail.wagtailcore.blocks import FieldBlock
from wagtailgeowidget.widgets import GeoField

def __init__(self, address_field=None, required=True, help_text=None,
                 **kwargs):
        self.field_options = {}
        self.address_field = address_field
        super(GeoBlock, self).__init__(**kwargs)

    @cached_property
    def field(self):
        field_kwargs = {'widget': GeoField(
            srid=4326,
            id_prefix='',
            address_field=self.address_field,
        )}
        field_kwargs.update(self.field_options)
        return forms.CharField(**field_kwargs)

    def clean(self, value):
        if not value:
            value = "SRID={};POINT({} {})".format(
                4326,
                GEO_WIDGET_DEFAULT_LOCATION['lng'],
                GEO_WIDGET_DEFAULT_LOCATION['lat']
            )
        return super(GeoBlock, self).clean(value)

    def render_form(self, value, prefix='', errors=None):
        if value and isinstance(value, dict):
            value = "SRID={};POINT({} {})".format(value['srid'],
                                                  value['lng'],
                                                  value['lat'])
        return super(GeoBlock, self).render_form(value, prefix, errors)

    def to_python(self, value):
        if isinstance(value, dict):
            return value

        value = geosgeometry_str_to_struct(value)
        value = {
            'lat': value['y'],
            'lng': value['x'],
            'srid': value['srid'],
        }

        return super(MapBlock, self).to_python(value)

这基本上就是wagtail块的结构。