def instance_info(request, instance): """ Get all the info we need about a given instance If also includes info about the fields available for the instance. If a user has been specified the field info will be tailored to that user """ user = request.user role = instance.default_role if user and not user.is_anonymous(): instance_user = user.get_instance_user(instance) if instance_user: role = instance_user.role perms = {} for fp in role.fieldpermission_set.all(): model = fp.model_name.lower() if fp.allows_reads: if model not in perms: perms[model] = [] if is_json_field_reference(fp.field_name): choices = None data_type = "string" else: model_inst = safe_get_model_class(fp.model_name)(instance=instance) data_type, _, choices = field_type_label_choices(model_inst, fp.field_name, fp.display_field_name) digits = get_digits_if_formattable(instance, model, fp.field_name) units = get_units_if_convertible(instance, model, fp.field_name) perms[model].append( { "data_type": data_type, "choices": choices, "units": units, "digits": digits, "can_write": fp.allows_writes, "display_name": fp.display_field_name, "field_name": fp.field_name, } ) info = _instance_info_dict(instance) info["fields"] = perms info["search"] = instance.advanced_search_fields return info
def add_perms(field_permissions, perms): for fp in field_permissions: model = fp.model_name.lower() field_key = '%s.%s' % (model, fp.field_name) if fp.allows_reads: if field_key in collection_udf_dict: choices = [] data_type = json.loads( collection_udf_dict[field_key].datatype) elif is_json_field_reference(fp.field_name): choices = None data_type = "string" else: model_inst = safe_get_model_class( fp.model_name)(instance=instance) data_type, __, __, choices = field_type_label_choices( model_inst, fp.field_name, fp.display_field_name) digits = get_digits_if_formattable(instance, model, fp.field_name) units = get_units_if_convertible(instance, model, fp.field_name) factor = 1.0 try: factor = storage_to_instance_units_factor( instance, model, fp.field_name) except KeyError: pass perms[field_key] = { 'data_type': data_type, 'choices': choices, 'units': units, 'digits': digits, 'canonical_units_factor': 1.0 / factor, 'can_write': fp.allows_writes, 'display_name': fp.display_field_name, 'field_name': fp.field_name, 'field_key': field_key, 'is_collection': field_key in collection_udf_dict }
def add_perms(field_permissions, perms): for fp in field_permissions: model = fp.model_name.lower() field_key = '%s.%s' % (model, fp.field_name) if fp.allows_reads: if field_key in collection_udf_dict: choices = [] data_type = json.loads( collection_udf_dict[field_key].datatype) elif is_json_field_reference(fp.field_name): choices = None data_type = "string" else: model_inst = safe_get_model_class(fp.model_name)( instance=instance) data_type, __, __, choices = field_type_label_choices( model_inst, fp.field_name, fp.display_field_name) digits = get_digits_if_formattable( instance, model, fp.field_name) units = get_units_if_convertible( instance, model, fp.field_name) factor = 1.0 try: factor = storage_to_instance_units_factor( instance, model, fp.field_name) except KeyError: pass perms[field_key] = { 'data_type': data_type, 'choices': choices, 'units': units, 'digits': digits, 'canonical_units_factor': 1.0 / factor, 'can_write': fp.allows_writes, 'display_name': fp.display_field_name, 'field_name': fp.field_name, 'field_key': field_key, 'is_collection': field_key in collection_udf_dict }
def mobile_search_fields(instance): from treemap.templatetags.form_extras import (field_type_label_choices, ADD_BLANK_NEVER) search_fields = copy.deepcopy(instance.mobile_search_fields) for field in search_fields['standard']: identifier = field['identifier'] alert_info = get_alert_field_info(identifier, instance) if alert_info is not None: field.update(alert_info) continue Model, field_name = _parse_field_info(instance, field) set_search_field_label(instance, field) field_type, __, __, choices = field_type_label_choices( Model, field_name, add_blank=ADD_BLANK_NEVER) if identifier == 'species.id': field['search_type'] = 'SPECIES' elif field_type in {'int', 'float'}: field['search_type'] = 'RANGE' elif field_type in {'date', 'datetime'}: field['search_type'] = 'DATERANGE' elif field_type == 'string': field['search_type'] = 'STRING' elif field_type == 'bool': field['search_type'] = 'BOOL' elif field_type == 'choice': field['search_type'] = 'CHOICE' elif field_type == 'multichoice': field['search_type'] = 'MULTICHOICE' if choices: field['choices'] = choices for field in search_fields['missing']: _set_missing_search_label(instance, field) return search_fields
def get_search_field_label(instance, field_info): """ Searches for missing data are controlled by fields, and those fields need labels. Two wrinkles: 1) Fields like species.id and mapFeaturePhoto.id need special handling. 2) Fields from all models are shown in the "Missing Data" category, so prefix the field name with the model name. """ from treemap.templatetags.form_extras import field_type_label_choices Model, field_name = _parse_field_info(instance, field_info) if field_name == 'id': if hasattr(Model, 'terminology'): label = Model.terminology(instance)['plural'] else: label = Model._meta.verbose_name_plural else: __, label, __, __ = field_type_label_choices(Model, field_name, '') if hasattr(Model, 'terminology'): prefix = force_text(Model.terminology(instance)['singular']) else: prefix = force_text(Model._meta.verbose_name) label = force_text(label) if not label.startswith(prefix): label = "%s %s" % (prefix, label) return label
def instance_info(request, instance): """ Get all the info we need about a given instance If also includes info about the fields available for the instance. If a user has been specified the field info will be tailored to that user """ user = request.user role = instance.default_role if user and not user.is_anonymous(): instance_user = user.get_instance_user(instance) if instance_user: role = instance_user.role perms = {} fields_to_allow = instance.mobile_api_fields for fp in role.fieldpermission_set.all(): model = fp.model_name.lower() if fields_to_allow and \ fp.field_name not in fields_to_allow.get(model, []): continue if fp.allows_reads: if model not in perms: perms[model] = [] if is_json_field_reference(fp.field_name): choices = None data_type = "string" else: model_inst = safe_get_model_class(fp.model_name)( instance=instance) data_type, _, choices = field_type_label_choices( model_inst, fp.field_name, fp.display_field_name) digits = get_digits_if_formattable( instance, model, fp.field_name) units = get_units_if_convertible( instance, model, fp.field_name) factor = 1.0 try: factor = get_conversion_factor( instance, model, fp.field_name) except KeyError: pass perms[model].append({ 'data_type': data_type, 'choices': choices, 'units': units, 'digits': digits, 'canonical_units_factor': 1.0 / factor, 'can_write': fp.allows_writes, 'display_name': fp.display_field_name, 'field_name': fp.field_name, 'field_key': '%s.%s' % (model, fp.field_name) }) info = _instance_info_dict(instance) info['fields'] = perms info['search'] = instance.mobile_search_fields public_config_keys = ['scss_variables'] info['config'] = {x: instance.config[x] for x in instance.config if x in public_config_keys} if instance.logo: info['logoUrl'] = instance.logo.url return info
def instance_info(request, instance): """ Get all the info we need about a given instance It also includes info about the fields available for the instance. If a user has been specified the field info will be tailored to that user """ user = request.user role = instance.default_role if user and not user.is_anonymous(): instance_user = user.get_instance_user(instance) if instance_user: role = instance_user.role collection_udfs = instance.userdefinedfielddefinition_set\ .filter(iscollection=True) collection_udf_dict = { "%s.%s" % (udf.model_type.lower(), udf.canonical_name): udf for udf in collection_udfs } # collect perms for the given role/instance into a serializable # dictionary. If a field isn't at least readable, it doesn't # get sent over at all. perms = {} for fp in role_permissions(role, instance): model = fp.model_name.lower() field_key = '%s.%s' % (model, fp.field_name) if fp.allows_reads: if field_key in collection_udf_dict: choices = [] data_type = json.loads(collection_udf_dict[field_key].datatype) elif is_json_field_reference(fp.field_name): choices = None data_type = "string" else: model_inst = safe_get_model_class( fp.model_name)(instance=instance) data_type, __, choices = field_type_label_choices( model_inst, fp.field_name, fp.display_field_name) digits = get_digits_if_formattable(instance, model, fp.field_name) units = get_units_if_convertible(instance, model, fp.field_name) factor = 1.0 try: factor = get_conversion_factor(instance, model, fp.field_name) except KeyError: pass perms[field_key] = { 'data_type': data_type, 'choices': choices, 'units': units, 'digits': digits, 'canonical_units_factor': 1.0 / factor, 'can_write': fp.allows_writes, 'display_name': fp.display_field_name, 'field_name': fp.field_name, 'field_key': field_key, 'is_collection': field_key in collection_udf_dict } def get_key_for_group(field_group): for key in ('collection_udf_keys', 'field_keys'): if key in field_group: return key return None # Remove fields from mobile_api_fields if they are not present in perms # (Generally because the user doesn't have read permissions) # If no fields are left in a group, remove the group mobile_api_fields = copy.deepcopy(instance.mobile_api_fields) for field_group in mobile_api_fields: # Field group headers are stored in English, and translated when they # are sent out to the client field_group['header'] = _(field_group['header']) key = get_key_for_group(field_group) if key: field_group[key] = [ field for field in field_group[key] if field in perms ] readable_mobile_api_fields = [ group for group in mobile_api_fields if group.get(get_key_for_group(group), None) ] info = _instance_info_dict(instance) info['fields'] = perms info['field_key_groups'] = readable_mobile_api_fields info['search'] = instance.mobile_search_fields info['date_format'] = _unicode_dateformat(instance.date_format) info['short_date_format'] = _unicode_dateformat(instance.short_date_format) info['meta_perms'] = { 'can_add_tree': perms_lib.plot_is_creatable(role), 'can_edit_tree': perms_lib.plot_is_writable(role), 'can_edit_tree_photo': perms_lib.treephoto_is_writable(role), } public_config_keys = ['scss_variables'] info['config'] = { x: instance.config[x] for x in instance.config if x in public_config_keys } if instance.logo: info['logoUrl'] = instance.logo.url return info
def instance_info(request, instance): """ Get all the info we need about a given instance It also includes info about the fields available for the instance. If a user has been specified the field info will be tailored to that user """ user = request.user role = instance.default_role if user and not user.is_anonymous(): instance_user = user.get_instance_user(instance) if instance_user: role = instance_user.role collection_udfs = instance.collection_udfs collection_udf_dict = {"%s.%s" % (udf.model_type.lower(), udf.canonical_name): udf for udf in collection_udfs} # collect perms for the given role/instance into a serializable # dictionary. If a field isn't at least readable, it doesn't # get sent over at all. perms = {} for fp in role_permissions(role, instance): model = fp.model_name.lower() field_key = '%s.%s' % (model, fp.field_name) if fp.allows_reads: if field_key in collection_udf_dict: choices = [] data_type = json.loads(collection_udf_dict[field_key].datatype) elif is_json_field_reference(fp.field_name): choices = None data_type = "string" else: model_inst = safe_get_model_class(fp.model_name)( instance=instance) data_type, __, choices = field_type_label_choices( model_inst, fp.field_name, fp.display_field_name) digits = get_digits_if_formattable( instance, model, fp.field_name) units = get_units_if_convertible( instance, model, fp.field_name) factor = 1.0 try: factor = storage_to_instance_units_factor( instance, model, fp.field_name) except KeyError: pass perms[field_key] = { 'data_type': data_type, 'choices': choices, 'units': units, 'digits': digits, 'canonical_units_factor': 1.0 / factor, 'can_write': fp.allows_writes, 'display_name': fp.display_field_name, 'field_name': fp.field_name, 'field_key': field_key, 'is_collection': field_key in collection_udf_dict } def get_key_for_group(field_group): for key in ('collection_udf_keys', 'field_keys'): if key in field_group: return key return None # Remove fields from mobile_api_fields if they are not present in perms # (Generally because the user doesn't have read permissions) # If no fields are left in a group, remove the group mobile_api_fields = copy.deepcopy(instance.mobile_api_fields) for field_group in mobile_api_fields: # Field group headers are stored in English, and translated when they # are sent out to the client field_group['header'] = _(field_group['header']) key = get_key_for_group(field_group) if key: field_group[key] = [field for field in field_group[key] if field in perms] readable_mobile_api_fields = [group for group in mobile_api_fields if group.get(get_key_for_group(group), None)] info = _instance_info_dict(instance) info['fields'] = perms info['field_key_groups'] = readable_mobile_api_fields info['search'] = mobile_search_fields(instance) info['date_format'] = _unicode_dateformat(instance.date_format) info['short_date_format'] = _unicode_dateformat(instance.short_date_format) info['meta_perms'] = { 'can_add_tree': perms_lib.plot_is_creatable(role), 'can_edit_tree': perms_lib.plot_is_writable(role), 'can_edit_tree_photo': perms_lib.treephoto_is_writable(role), } public_config_keys = ['scss_variables'] info['config'] = {x: instance.config[x] for x in instance.config if x in public_config_keys} if instance.logo: info['logoUrl'] = instance.logo.url return info
def instance_info(request, instance): """ Get all the info we need about a given instance It also includes info about the fields available for the instance. If a user has been specified the field info will be tailored to that user """ user = request.user role = instance.default_role if user and not user.is_anonymous(): instance_user = user.get_instance_user(instance) if instance_user: role = instance_user.role collection_udfs = instance.userdefinedfielddefinition_set\ .filter(iscollection=True) collection_udf_dict = {"%s.%s" % (udf.model_type.lower(), udf.canonical_name): udf for udf in collection_udfs} # collect perms for the given role/instance into a serializable # dictionary. If a field isn't at least readable, it doesn't # get sent over at all. perms = {} for fp in role_permissions(role, instance): model = fp.model_name.lower() field_key = '%s.%s' % (model, fp.field_name) if fp.allows_reads: if field_key in collection_udf_dict: choices = [] data_type = collection_udf_dict[field_key].datatype elif is_json_field_reference(fp.field_name): choices = None data_type = "string" else: model_inst = safe_get_model_class(fp.model_name)( instance=instance) data_type, _, choices = field_type_label_choices( model_inst, fp.field_name, fp.display_field_name) digits = get_digits_if_formattable( instance, model, fp.field_name) units = get_units_if_convertible( instance, model, fp.field_name) factor = 1.0 try: factor = get_conversion_factor( instance, model, fp.field_name) except KeyError: pass perms[field_key] = { 'data_type': data_type, 'choices': choices, 'units': units, 'digits': digits, 'canonical_units_factor': 1.0 / factor, 'can_write': fp.allows_writes, 'display_name': fp.display_field_name, 'field_name': fp.field_name, 'field_key': field_key, 'is_collection': field_key in collection_udf_dict } info = _instance_info_dict(instance) info['fields'] = perms info['field_key_groups'] = instance.mobile_api_fields info['search'] = instance.mobile_search_fields info['date_format'] = _unicode_dateformat(instance.date_format) info['short_date_format'] = _unicode_dateformat(instance.short_date_format) info['meta_perms'] = { 'can_add_tree': perms_lib.plot_is_creatable(role), 'can_edit_tree': perms_lib.plot_is_writable(role), 'can_edit_tree_photo': perms_lib.treephoto_is_writable(role), } public_config_keys = ['scss_variables'] info['config'] = {x: instance.config[x] for x in instance.config if x in public_config_keys} if instance.logo: info['logoUrl'] = instance.logo.url return info
def instance_info(request, instance): """ Get all the info we need about a given instance If also includes info about the fields available for the instance. If a user has been specified the field info will be tailored to that user """ user = request.user role = instance.default_role if user and not user.is_anonymous(): instance_user = user.get_instance_user(instance) if instance_user: role = instance_user.role perms = {} collection_udfs = instance.userdefinedfielddefinition_set\ .filter(iscollection=True) collection_udf_dict = { "%s.%s" % (udf.model_type.lower(), udf.canonical_name): udf for udf in collection_udfs } for fp in role.fieldpermission_set.all(): model = fp.model_name.lower() field_key = '%s.%s' % (model, fp.field_name) if fp.allows_reads: if field_key in collection_udf_dict: choices = [] data_type = collection_udf_dict[field_key].datatype elif is_json_field_reference(fp.field_name): choices = None data_type = "string" else: model_inst = safe_get_model_class( fp.model_name)(instance=instance) data_type, _, choices = field_type_label_choices( model_inst, fp.field_name, fp.display_field_name) digits = get_digits_if_formattable(instance, model, fp.field_name) units = get_units_if_convertible(instance, model, fp.field_name) factor = 1.0 try: factor = get_conversion_factor(instance, model, fp.field_name) except KeyError: pass perms[field_key] = { 'data_type': data_type, 'choices': choices, 'units': units, 'digits': digits, 'canonical_units_factor': 1.0 / factor, 'can_write': fp.allows_writes, 'display_name': fp.display_field_name, 'field_name': fp.field_name, 'field_key': field_key, 'is_collection': field_key in collection_udf_dict } info = _instance_info_dict(instance) info['fields'] = perms info['field_key_groups'] = instance.mobile_api_fields info['search'] = instance.mobile_search_fields public_config_keys = ['scss_variables'] info['config'] = { x: instance.config[x] for x in instance.config if x in public_config_keys } if instance.logo: info['logoUrl'] = instance.logo.url return info
def advanced_search_fields(instance, user): from treemap.util import get_model_for_instance from treemap.templatetags.form_extras import field_type_label_choices from treemap.models import Tree, MapFeature # prevent circular import def make_display_filter(feature_name): if feature_name == 'Plot': plural = _('empty planting sites') feature_name = 'EmptyPlot' else: plural = get_plural_feature_name(feature_name) return { 'label': _('Show %(models)s') % { 'models': plural.lower() }, 'model': feature_name } def get_plural_feature_name(feature_name): if feature_name == 'Tree': Feature = Tree else: Feature = MapFeature.get_subclass(feature_name) return Feature.terminology(instance)['plural'] def parse_field_info(field_info): model_name, field_name = field_info['identifier'].split('.', 2) model = get_model_for_instance(model_name, instance) return model, field_name def get_visible_fields(fields, user): visible_fields = [] for field in fields: model, field_name = parse_field_info(field) if model.field_is_visible(user, field_name): visible_fields.append(field) return visible_fields fields = copy.deepcopy(instance.search_config) fields = { model: get_visible_fields(fields, user) for model, fields in fields.iteritems() } for field_info in fields.get('missing', []): model, field_name = parse_field_info(field_info) if field_name == 'id': if hasattr(model, 'terminology'): label = model.terminology(instance)['plural'] else: label = model._meta.verbose_name_plural else: __, label, __ = field_type_label_choices(model, field_name, '') field_info['label'] = _('Show missing %(field)s') % { 'field': label.lower() } field_info['search_type'] = 'ISNULL' field_info['value'] = 'true' fields['display'] = [ make_display_filter('Tree'), make_display_filter('Plot') ] fields['display'] += [ make_display_filter(feature) for feature in sorted(instance.map_feature_types) if feature != 'Plot' ] num = 0 for filters in fields.itervalues(): for field in filters: # It makes styling easier if every field has an identifier field['id'] = "%s_%s" % (field.get('identifier', ''), num) num += 1 more = [] for feature_name in sorted(instance.map_feature_types): if feature_name in fields and feature_name != 'Plot': filters = fields.pop(feature_name) filters = get_visible_fields(filters, user) if len(filters) > 0: more.append({ 'name': feature_name, 'title': get_plural_feature_name(feature_name), 'fields': filters }) fields['more'] = more return fields
def advanced_search_fields(instance, user): from treemap.util import get_model_for_instance from treemap.templatetags.form_extras import field_type_label_choices from treemap.models import Tree, MapFeature # prevent circular import def make_display_filter(feature_name): if feature_name == 'Plot': plural = _('empty planting sites') feature_name = 'EmptyPlot' else: plural = get_plural_feature_name(feature_name) return { 'label': _('Show %(models)s') % {'models': plural.lower()}, 'model': feature_name } def get_plural_feature_name(feature_name): if feature_name == 'Tree': Feature = Tree else: Feature = MapFeature.get_subclass(feature_name) return Feature.terminology(instance)['plural'] def parse_field_info(field_info): model_name, field_name = field_info['identifier'].split('.', 2) model = get_model_for_instance(model_name, instance) return model, field_name def get_visible_fields(fields, user): visible_fields = [] for field in fields: model, field_name = parse_field_info(field) if model.field_is_visible(user, field_name): visible_fields.append(field) return visible_fields fields = copy.deepcopy(instance.search_config) fields = {model: get_visible_fields(fields, user) for model, fields in fields.iteritems()} for field_info in fields.get('missing', []): model, field_name = parse_field_info(field_info) if field_name == 'id': if hasattr(model, 'terminology'): label = model.terminology(instance)['plural'] else: label = model._meta.verbose_name_plural else: __, label, __ = field_type_label_choices(model, field_name, '') field_info['label'] = _('Show missing %(field)s') % { 'field': label.lower()} field_info['search_type'] = 'ISNULL' field_info['value'] = 'true' fields['display'] = [make_display_filter('Tree'), make_display_filter('Plot')] fields['display'] += [ make_display_filter(feature) for feature in sorted(instance.map_feature_types) if feature != 'Plot'] num = 0 for filters in fields.itervalues(): for field in filters: # It makes styling easier if every field has an identifier field['id'] = "%s_%s" % (field.get('identifier', ''), num) num += 1 more = [] for feature_name in sorted(instance.map_feature_types): if feature_name in fields and feature_name != 'Plot': filters = fields.pop(feature_name) filters = get_visible_fields(filters, user) if len(filters) > 0: more.append({ 'name': feature_name, 'title': get_plural_feature_name(feature_name), 'fields': filters }) fields['more'] = more return fields