Beispiel #1
0
 def test_get_display_value_no_unit_conversion_when_same_units(self):
     set_attr_on_json_field(
         self.instance, 'config.value_display.test.unit_only.units', 'ft')
     val, display_val = get_display_value(
         self.instance, 'test', 'unit_only', 1)
     self.assertEqual(val, 1)
     self.assertEqual(display_val, '1.0')
Beispiel #2
0
 def test_get_display_value_conversion(self):
     set_attr_on_json_field(
         self.instance, 'config.value_display.test.both.units', 'in')
     val, display_val = get_display_value(
         self.instance, 'test', 'both', 1)
     self.assertAlmostEqual(val, 12)
     self.assertEqual(display_val, '12.000')
Beispiel #3
0
def format_benefits(instance, benefits, basis):
    currency_symbol = ''
    if instance.eco_benefits_conversion:
        currency_symbol = instance.eco_benefits_conversion.currency_symbol

    # FYI: this mutates the underlying benefit dictionaries
    for benefit_group in benefits.values():
        for key, benefit in benefit_group.iteritems():
            if benefit['currency'] is not None:
                # TODO: Use i18n/l10n to format currency
                benefit['currency_saved'] = currency_symbol + number_format(
                    benefit['currency'], decimal_pos=0)

            unit_key = benefit.get('unit-name')

            if unit_key:
                _, value = get_display_value(
                    instance, unit_key, key, benefit['value'])

                benefit['name'] = key
                benefit['value'] = value
                benefit['unit'] = get_units(instance, unit_key, key)

    # Add total and percent to basis
    rslt = {'benefits': benefits,
            'currency_symbol': currency_symbol,
            'basis': basis}

    return rslt
Beispiel #4
0
def format_benefits(instance, benefits, basis):
    currency_symbol = ''
    if instance.eco_benefits_conversion:
        currency_symbol = instance.eco_benefits_conversion.currency_symbol

    # FYI: this mutates the underlying benefit dictionaries
    for benefit_group in benefits.values():
        for key, benefit in benefit_group.iteritems():
            if benefit['currency'] is not None:
                # TODO: Use i18n/l10n to format currency
                benefit['currency_saved'] = currency_symbol + number_format(
                    benefit['currency'], decimal_pos=0)

            unit_key = benefit.get('unit-name')

            if unit_key:
                _, value = get_display_value(instance, unit_key, key,
                                             benefit['value'])

                benefit['name'] = key
                benefit['value'] = value
                benefit['unit'] = get_units(instance, unit_key, key)

    # Add total and percent to basis
    rslt = {
        'benefits': benefits,
        'currency_symbol': currency_symbol,
        'basis': basis
    }

    return rslt
Beispiel #5
0
 def test_get_display_value_no_unit_conversion_when_same_units(self):
     set_attr_on_json_field(
         self.instance, 'config.value_display.test.unit_only.units', 'ft')
     val, display_val = get_display_value(
         self.instance, 'test', 'unit_only', 1)
     self.assertEqual(val, 1)
     self.assertEqual(display_val, '1.0')
Beispiel #6
0
 def test_get_display_value_conversion(self):
     set_attr_on_json_field(
         self.instance, 'config.value_display.test.both.units', 'in')
     val, display_val = get_display_value(
         self.instance, 'test', 'both', 1)
     self.assertAlmostEqual(val, 12)
     self.assertEqual(display_val, '12.000')
Beispiel #7
0
def context_dict_for_resource(request, resource, **kwargs):
    context = context_dict_for_map_feature(request, resource, **kwargs)
    instance = request.instance

    # Give them 2 for adding the resource and answering its questions
    total_progress_items = 3
    completed_progress_items = 2

    context['external_link'] = None

    photos = resource.photos()
    context['photos'] = [context_dict_for_photo(request, photo)
                         for photo in photos]

    has_photos = len(photos) > 0

    if has_photos:
        completed_progress_items += 1

    context['upload_photo_endpoint'] = reverse(
        'add_photo_to_map_feature',
        kwargs={'instance_url_name': instance.url_name,
                'feature_id': resource.pk})

    context['progress_percent'] = int(100 * (
        completed_progress_items / total_progress_items) + .5)

    context['progress_messages'] = []
    if not has_photos:
        context['progress_messages'].append(_('Add a photo'))

    audits = _map_feature_audits(request.user, request.instance, resource)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    object_name_alias = to_object_name(context['feature'].__class__.__name__)
    # some features that were originally written to support plot and tree
    # have grown to support other resource types, but they expect a context
    # entry for their type, not just for 'feature'.
    # For example:
    # * Plot detail expects 'plot' and 'tree'
    # * Foo detail would expect 'foo'
    context[object_name_alias] = context['feature']

    if isinstance(resource, PolygonalMapFeature):
        context['contained_plots'] = resource.contained_plots()
        area = resource.calculate_area()
        __, display_area = get_display_value(instance,
                                             'greenInfrastructure', 'area',
                                             area, digits=0)
        display_units = get_unit_abbreviation(
            get_units(instance, 'greenInfrastructure', 'area'))
        context['area'] = area
        context['display_area'] = display_area
        context['area_units'] = display_units

    return context
def context_dict_for_resource(request, resource, **kwargs):
    context = context_dict_for_map_feature(request, resource, **kwargs)
    instance = request.instance

    # Give them 2 for adding the resource and answering its questions
    total_progress_items = 3
    completed_progress_items = 2

    context['external_link'] = None

    photos = resource.photos()
    context['photos'] = [
        context_dict_for_photo(request, photo) for photo in photos
    ]

    has_photos = len(photos) > 0

    if has_photos:
        completed_progress_items += 1

    context['upload_photo_endpoint'] = reverse('add_photo_to_map_feature',
                                               kwargs={
                                                   'instance_url_name':
                                                   instance.url_name,
                                                   'feature_id': resource.pk
                                               })

    context['progress_percent'] = int(
        100 * (completed_progress_items / total_progress_items) + .5)

    context['progress_messages'] = []
    if not has_photos:
        context['progress_messages'].append(_('Add a photo'))

    audits = _map_feature_audits(request.user, request.instance, resource)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    object_name_alias = to_object_name(context['feature'].__class__.__name__)
    # some features that were originally written to support plot and tree
    # have grown to support other resource types, but they expect a context
    # entry for their type, not just for 'feature'.
    # For example:
    # * Plot detail expects 'plot' and 'tree'
    # * Foo detail would expect 'foo'
    context[object_name_alias] = context['feature']

    if isinstance(resource, PolygonalMapFeature):
        context['contained_plots'] = resource.contained_plots()
        __, display_area = get_display_value(instance, 'greenInfrastructure',
                                             'area', resource.calculate_area())
        display_units = get_unit_abbreviation(
            get_units(instance, 'greenInfrastructure', 'area'))
        context['area'] = '{} {}'.format(display_area, display_units)

    return context
def site_config_green_infrastructure(request, instance):
    def _get_form_fields(defaults, thing):
        form_fields = []
        for form in ('singular', 'plural'):
            term_getter = 'terms.%s.%s' % (thing, form)
            val = instance.config.get(term_getter, defaults.get(form))
            form_fields.append({
                'display_value': val,
                'value': val,
                'data_type': 'text',
                'identifier': 'instance.config.%s' % term_getter,
            })
        return form_fields

    terminology_fields = {thing: _get_form_fields(defaults, thing)
                          for thing, defaults in REPLACEABLE_TERMS.items()}

    __, annual_rainfall_display_value = get_display_value(
        instance, 'greenInfrastructure', 'rainfall',
        instance.annual_rainfall_inches)
    annual_rainfall_fields = [(
        _('Annual Rainfall'),
        {
            'identifier': 'instance.config.annual_rainfall_inches',
            'data_type': 'float',
            'display_value': annual_rainfall_display_value,
            'value': annual_rainfall_display_value
        },
        get_units(instance, 'greenInfrastructure', 'rainfall'))]

    customizable_models = _get_replaceable_models(instance)

    gsi_model_fields = []
    for Cls in customizable_models:
        thing = Cls.__name__
        defaults = Cls.terminology()
        config = Cls.get_config(instance)

        gsi_model = {'label': defaults.get('singular', thing),
                     'model_name': thing,
                     'checked': thing in instance.map_feature_types,
                     'fields': _get_form_fields(defaults, thing),
                     'is_la_model': thing.lower().endswith('la')}
        gsi_model['diversion_rate'], gsi_model['diversion_rate_applies'] = \
            _get_diversion_rate_for_display(config)
        (gsi_model['should_show_eco'], gsi_model['should_show_eco_applies'],
         gsi_model['should_show_eco_indicator']) = \
            _get_should_show_eco(config)

        gsi_model_fields.append(gsi_model)

    return {
        'instance': instance,
        'terminology_fields': terminology_fields,
        'annual_rainfall_fields': annual_rainfall_fields,
        'gsi_model_fields': gsi_model_fields,
    }
Beispiel #10
0
    def _unit_format(self, value):
        model_name = self.model.lower()

        if is_convertible_or_formattable(model_name, self.field):
            _, value = get_display_value(
                self.instance, model_name, self.field, value)
        if value and is_convertible(model_name, self.field):
            units = get_units(self.instance, model_name, self.field)
            value += (' %s' % units)

        return value
Beispiel #11
0
    def displayize_benefit(key, currency_factor):
        benefit = benefits[key]

        if currency_factor:
            benefit["currency_saved"] = number_format(benefit["value"] * currency_factor, decimal_pos=0)

        _, value = get_display_value(instance, "eco", key, benefit["value"])
        benefit["value"] = value
        benefit["label"] = get_benefit_label(key)
        benefit["unit"] = get_units(instance, "eco", key)

        return benefit
Beispiel #12
0
    def displayize_benefit(key):
        benefit = benefits[key]

        if benefit['currency'] is not None:
            benefit['currency_saved'] = number_format(
                benefit['currency'], decimal_pos=0)

        _, value = get_display_value(instance, 'eco', key, benefit['value'])
        benefit['value'] = value
        benefit['label'] = get_benefit_label(key)
        benefit['unit'] = get_units(instance, 'eco', key)

        return benefit
Beispiel #13
0
def format_benefits(instance, benefits, basis, digits=None):
    # keep the top level module dependencies small
    from treemap.ecobenefits import BenefitCategory

    currency_symbol = ''
    if instance.eco_benefits_conversion:
        currency_symbol = instance.eco_benefits_conversion.currency_symbol

    # FYI: this mutates the underlying benefit dictionaries
    total_currency = 0
    for benefit_group in benefits.values():
        for key, benefit in benefit_group.iteritems():
            if benefit['currency'] is not None:
                # TODO: Use i18n/l10n to format currency
                benefit['currency_saved'] = currency_symbol + number_format(
                    benefit['currency'], decimal_pos=0)
                if BenefitCategory.is_annual_table.get(key, True):
                    total_currency += benefit['currency']

            unit_key = benefit.get('unit-name')

            if unit_key:
                __, value = get_display_value(instance, unit_key, key,
                                              benefit['value'], digits)

                benefit['name'] = key
                benefit['value'] = value
                benefit['unit'] = get_units(instance, unit_key, key)

    benefits['all'] = {
        'totals': {
            'value':
            None,
            'label':
            _('Total annual benefits'),
            'currency':
            total_currency,
            'currency_saved':
            currency_symbol + number_format(total_currency, decimal_pos=0)
        }
    }

    # Add total and percent to basis
    rslt = {
        'benefits': benefits,
        'benefits_total_currency': total_currency,
        'currency_symbol': currency_symbol,
        'basis': basis
    }

    return rslt
Beispiel #14
0
    def _unit_format(self, value):
        model_name = self.model.lower()

        if isinstance(value, GEOSGeometry):
            if value.geom_type == 'Point':
                return '%d,%d' % (value.x, value.y)
            if value.geom_type in {'MultiPolygon', 'Polygon'}:
                value = value.area

        if is_convertible_or_formattable(model_name, self.field):
            _, value = get_display_value(
                self.instance, model_name, self.field, value)
            if value and is_convertible(model_name, self.field):
                units = get_unit_name(get_units(self.instance,
                                                model_name, self.field))
                value += (' %s' % units)

        return value
Beispiel #15
0
    def _unit_format(self, value):
        model_name = self.model.lower()

        if isinstance(value, GEOSGeometry):
            if value.geom_type == 'Point':
                return '%d,%d' % (value.x, value.y)
            if value.geom_type in {'MultiPolygon', 'Polygon'}:
                value = value.area

        if is_convertible_or_formattable(model_name, self.field):
            _, value = get_display_value(self.instance, model_name, self.field,
                                         value)
            if value and is_convertible(model_name, self.field):
                units = get_unit_name(
                    get_units(self.instance, model_name, self.field))
                value += (' %s' % units)

        return value
Beispiel #16
0
def format_benefits(instance, benefits, basis, digits=None):
    # keep the top level module dependencies small
    from treemap.ecobenefits import BenefitCategory

    currency_symbol = ''
    if instance.eco_benefits_conversion:
        currency_symbol = instance.eco_benefits_conversion.currency_symbol

    # FYI: this mutates the underlying benefit dictionaries
    total_currency = 0
    for benefit_group in benefits.values():
        for key, benefit in benefit_group.iteritems():
            if benefit['currency'] is not None:
                # TODO: Use i18n/l10n to format currency
                benefit['currency_saved'] = currency_symbol + number_format(
                    benefit['currency'], decimal_pos=0)
                if BenefitCategory.is_annual_table.get(key, True):
                    total_currency += benefit['currency']

            unit_key = benefit.get('unit-name')

            if unit_key:
                __, value = get_display_value(
                    instance, unit_key, key, benefit['value'], digits)

                benefit['name'] = key
                benefit['value'] = value
                benefit['unit'] = get_units(instance, unit_key, key)

    benefits['all'] = {'totals': {
        'value': None,
        'label': _('Total annual benefits'),
        'currency': total_currency,
        'currency_saved': currency_symbol + number_format(
            total_currency, decimal_pos=0)}}

    # Add total and percent to basis
    rslt = {'benefits': benefits,
            'benefits_total_currency': total_currency,
            'currency_symbol': currency_symbol,
            'basis': basis}

    return rslt
Beispiel #17
0
    def render(self, context):
        label, identifier = self.resolve_label_and_identifier(context)
        user = _resolve_variable(self.user, context)
        instance = _resolve_variable(self.instance, context)
        field_template = get_template(_resolve_variable(
                                      self.field_template, context))

        if not isinstance(identifier, basestring)\
           or not _identifier_regex.match(identifier):
            raise template.TemplateSyntaxError(
                'expected a string with the format "model.property" '
                'to follow "from" %s' % identifier)

        model_name, field_name = identifier.split('.', 1)
        model = self.get_model(context, model_name, instance)

        def _is_udf(model, udf_field_name):
            return (hasattr(model, 'udf_field_names') and
                    udf_field_name in model.udf_field_names)

        def _udf_dict(model, field_name):
            return model.get_user_defined_fields()\
                .filter(name=field_name.replace('udf:', ''))[0]\
                .datatype_dict

        def _field_type_label_choices(model, field_name, label):
            choices = None
            udf_field_name = field_name.replace('udf:', '')
            if not _is_udf(model, udf_field_name):
                field = model._meta.get_field(field_name)
                field_type = field.get_internal_type()
                try:
                    field_type = FieldNode._field_mappings[field_type]
                except KeyError:
                    raise Exception('This template tag only supports %s not %s'
                                    % (FieldNode._valid_field_keys,
                                       field_type))
                label = label if label else field.help_text
                choices = [{'value': choice[0], 'display_value': choice[1]}
                           for choice in field.choices]
                if choices and field.null:
                    choices = [{'value': '', 'display_value': ''}] + choices
            else:
                udf_dict = _udf_dict(model, field_name)
                field_type = udf_dict['type']
                label = label if label else udf_field_name
                if 'choices' in udf_dict:
                    values = [''] + udf_dict['choices']
                    choices = [{'value': value, 'display_value': value}
                               for value in values]

            return field_type, label, choices

        def _field_value(model, field_name):
            udf_field_name = field_name.replace('udf:', '')
            if field_name in model._meta.get_all_field_names():
                try:
                    val = getattr(model, field_name)
                except ObjectDoesNotExist:
                    val = None
            elif _is_udf(model, udf_field_name):
                val = model.udfs[udf_field_name]
            else:
                raise ValueError('Could not find field: %s' % field_name)

            return val

        if is_json_field_reference(field_name):
            field_value = get_attr_from_json_field(model, field_name)
            choices = None
            is_visible = is_editable = True
            data_type = "string"
        else:
            field_value = _field_value(model, field_name)
            data_type, label, choices = _field_type_label_choices(
                model, field_name, label)

            if user is not None and hasattr(model, 'field_is_visible'):
                is_visible = model.field_is_visible(user, field_name)
                is_editable = model.field_is_editable(user, field_name)
            else:
                # This tag can be used without specifying a user. In that case
                # we assume that the content is visible and upstream code is
                # responsible for only showing the content to the appropriate
                # user
                is_visible = True
                is_editable = True

        digits = (get_digits(model.instance, model_name, field_name)
                  if is_formattable(model_name, field_name) else '')

        units = ''
        if is_convertible(model_name, field_name):
            units = get_units(model.instance, model_name, field_name)

        if field_value is None:
            display_val = None
        elif data_type == 'date' and model.instance:
            display_val = dateformat.format(field_value,
                                            model.instance.short_date_format)
        elif data_type == 'date':
            display_val = dateformat.format(field_value,
                                            settings.SHORT_DATE_FORMAT)
        elif is_convertible_or_formattable(model_name, field_name):
            field_value, display_val = get_display_value(
                model.instance, model_name, field_name, field_value)
            if units is not '':
                display_val += (' %s' % units)
        else:
            display_val = unicode(field_value)

        context['field'] = {
            'label': label,
            'identifier': identifier,
            'value': field_value,
            'display_value': display_val,
            'units': units,
            'digits': digits,
            'data_type': data_type,
            'is_visible': is_visible,
            'is_editable': is_editable,
            'choices': choices
        }
        self.get_additional_context(context['field'])

        return field_template.render(context)
Beispiel #18
0
 def test_separate_storage_and_display_defaults(self):
     val, display_val = get_display_value(
         self.instance, 'test', 'separate_units', 12)
     self.assertEqual(val, 1)
     self.assertEqual(display_val, '1.0')
def site_config_green_infrastructure(request, instance):
    def _get_form_fields(defaults, thing):
        form_fields = []
        for form in ('singular', 'plural'):
            term_getter = 'terms.%s.%s' % (thing, form)
            val = instance.config.get(term_getter, defaults.get(form))
            form_fields.append({
                'display_value':
                val,
                'value':
                val,
                'data_type':
                'text',
                'identifier':
                'instance.config.%s' % term_getter,
            })
        return form_fields

    terminology_fields = {
        thing: _get_form_fields(defaults, thing)
        for thing, defaults in REPLACEABLE_TERMS.items()
    }

    __, annual_rainfall_display_value = get_display_value(
        instance, 'greenInfrastructure', 'rainfall',
        instance.annual_rainfall_inches)
    annual_rainfall_fields = [(_('Annual Rainfall'), {
        'identifier': 'instance.config.annual_rainfall_inches',
        'data_type': 'float',
        'display_value': annual_rainfall_display_value,
        'value': annual_rainfall_display_value
    }, get_units(instance, 'greenInfrastructure', 'rainfall'))]

    customizable_models = _get_replaceable_models(instance)

    gsi_model_fields = []
    for Cls in customizable_models:
        thing = Cls.__name__
        defaults = Cls.terminology()
        config = Cls.get_config(instance)

        gsi_model = {
            'label': defaults.get('singular', thing),
            'model_name': thing,
            'checked': thing in instance.map_feature_types,
            'fields': _get_form_fields(defaults, thing),
            'is_la_model': thing.lower().endswith('la')
        }
        gsi_model['diversion_rate'], gsi_model['diversion_rate_applies'] = \
            _get_diversion_rate_for_display(config)
        (gsi_model['should_show_eco'], gsi_model['should_show_eco_applies'],
         gsi_model['should_show_eco_indicator']) = \
            _get_should_show_eco(config)

        gsi_model_fields.append(gsi_model)

    return {
        'instance': instance,
        'terminology_fields': terminology_fields,
        'annual_rainfall_fields': annual_rainfall_fields,
        'gsi_model_fields': gsi_model_fields,
    }
Beispiel #20
0
 def test_get_display_value_float_formatting(self):
     val, display_val = get_display_value(
         self.instance, 'test', 'digit_only', 1)
     self.assertEqual(val, 1)
     self.assertEqual(display_val, '1.00')
Beispiel #21
0
 def test_get_display_value_no_unit_conversion_when_same_units(self):
     set_attr_on_json_field(self.instance, "config.value_display.test.unit_only.units", "ft")
     val, display_val = get_display_value(self.instance, "test", "unit_only", 1)
     self.assertEqual(val, 1)
     self.assertEqual(display_val, "1.0")
Beispiel #22
0
 def test_get_display_value_float_formatting(self):
     val, display_val = get_display_value(self.instance, "test", "digit_only", 1)
     self.assertEqual(val, 1)
     self.assertEqual(display_val, "1.00")
Beispiel #23
0
 def test_get_display_value_conversion(self):
     set_attr_on_json_field(self.instance, "config.value_display.test.both.units", "in")
     val, display_val = get_display_value(self.instance, "test", "both", 1)
     self.assertAlmostEqual(val, 12)
     self.assertEqual(display_val, "12.000")
Beispiel #24
0
 def test_separate_storage_and_display_defaults(self):
     val, display_val = get_display_value(self.instance, "test", "separate_units", 12)
     self.assertEqual(val, 1)
     self.assertEqual(display_val, "1.0")
Beispiel #25
0
 def test_separate_storage_and_display_defaults(self):
     val, display_val = get_display_value(self.instance, 'test',
                                          'separate_units', 12)
     self.assertEqual(val, 1)
     self.assertEqual(display_val, '1.0')
Beispiel #26
0
 def test_get_display_value_float_formatting(self):
     val, display_val = get_display_value(self.instance, 'test',
                                          'digit_only', 1)
     self.assertEqual(val, 1)
     self.assertEqual(display_val, '1.00')
Beispiel #27
0
    def render(self, context):
        label, identifier = self.resolve_label_and_identifier(context)
        user = _resolve_variable(self.user, context)
        instance = _resolve_variable(self.instance, context)
        field_template = get_template(_resolve_variable(
                                      self.field_template, context))

        if not isinstance(identifier, basestring)\
           or not _identifier_regex.match(identifier):
            raise template.TemplateSyntaxError(
                'expected a string with the format "model.property" '
                'to follow "from" %s' % identifier)

        model_name, field_name = identifier.split('.', 1)
        model = self.get_model(context, model_name, instance)

        def _field_value(model, field_name):
            udf_field_name = field_name.replace('udf:', '')
            if field_name in model._meta.get_all_field_names():
                try:
                    val = getattr(model, field_name)
                except ObjectDoesNotExist:
                    val = None
            elif _is_udf(model, udf_field_name):
                val = model.udfs[udf_field_name]
            else:
                raise ValueError('Could not find field: %s' % field_name)

            return val

        if is_json_field_reference(field_name):
            field_value = get_attr_from_json_field(model, field_name)
            choices = None
            is_visible = is_editable = True
            data_type = "string"
        else:
            field_value = _field_value(model, field_name)
            data_type, label, choices = field_type_label_choices(
                model, field_name, label)

            if user is not None and hasattr(model, 'field_is_visible'):
                is_visible = model.field_is_visible(user, field_name)
                is_editable = model.field_is_editable(user, field_name)
            else:
                # This tag can be used without specifying a user. In that case
                # we assume that the content is visible and upstream code is
                # responsible for only showing the content to the appropriate
                # user
                is_visible = True
                is_editable = True

        digits = units = ''

        if hasattr(model, 'instance'):
            digits = get_digits_if_formattable(
                model.instance, model_name, field_name)

            units = get_units_if_convertible(
                model.instance, model_name, field_name)

        if field_value is None:
            display_val = None
        elif data_type == 'date' and model.instance:
            display_val = dateformat.format(field_value,
                                            model.instance.short_date_format)
        elif data_type == 'date':
            display_val = dateformat.format(field_value,
                                            settings.SHORT_DATE_FORMAT)
        elif is_convertible_or_formattable(model_name, field_name):
            field_value, display_val = get_display_value(
                model.instance, model_name, field_name, field_value)
            if units is not '':
                display_val += (' %s' % units)
        else:
            display_val = unicode(field_value)

        context['field'] = {
            'label': label,
            'identifier': identifier,
            'value': field_value,
            'display_value': display_val,
            'units': units,
            'digits': digits,
            'data_type': data_type,
            'is_visible': is_visible,
            'is_editable': is_editable,
            'choices': choices
        }
        self.get_additional_context(context['field'])

        return field_template.render(context)