@frontend.route('/objects/<int:object_id>', methods=['GET', 'POST'])
@object_permissions_required(Permissions.READ, on_unauthorized=on_unauthorized)
def object(object_id):
    object = get_object(object_id=object_id)
    related_objects_tree = logic.object_relationships.build_related_objects_tree(object_id, flask_login.current_user.id)
    user_language_id = get_user_language(flask_login.current_user).id
    english = get_language(Language.ENGLISH)
    object_languages = set()
    user_permissions = get_user_object_permissions(object_id=object_id, user_id=flask_login.current_user.id)
    user_may_edit = (Permissions.WRITE in user_permissions)
    user_may_grant = (Permissions.GRANT in user_permissions)
    user_may_use_as_template = (Permissions.READ in get_user_action_permissions(object.action_id, user_id=flask_login.current_user.id))
    action = get_action_with_translation_in_language(object.action_id, user_language_id, use_fallback=True)
    if (action.schema != object.schema):
        new_schema_available = True
    else:
        new_schema_available = False
    if ((not user_may_edit) and (flask.request.args.get('mode', '') == 'edit')):
        return flask.abort(403)
    if ((not user_may_edit) and (flask.request.args.get('mode', '') == 'upgrade')):
        return flask.abort(403)
    if (not flask.current_app.config['DISABLE_INLINE_EDIT']):
        if ((not user_may_edit) and (flask.request.args.get('mode', '') == 'inline_edit')):
            return flask.abort(403)
        if (user_may_edit and (flask.request.method == 'GET') and (flask.request.args.get('mode', '') in {'', 'inline_edit'})):
            return show_inline_edit(object, get_action(object.action_id))
    if ((flask.request.method == 'GET') and (flask.request.args.get('mode', '') not in ('edit', 'upgrade'))):
        instrument = (get_instrument_with_translation_in_language(action.instrument_id, user_language_id) if action.instrument else None)
        object_type = get_action_type_with_translation_in_language(action_type_id=action.type_id, language_id=user_language_id).translation.object_name
        object_log_entries = object_log.get_object_log_entries(object_id=object_id, user_id=flask_login.current_user.id)
        dataverse_enabled = bool(flask.current_app.config['DATAVERSE_URL'])
        if dataverse_enabled:
            dataverse_url = logic.dataverse_export.get_dataverse_url(object_id)
            show_dataverse_export = (user_may_grant and (not dataverse_url))
        else:
            dataverse_url = None
            show_dataverse_export = False
        if user_may_edit:
            serializer = itsdangerous.URLSafeTimedSerializer(flask.current_app.config['SECRET_KEY'], salt='mobile-upload')
            token = serializer.dumps([flask_login.current_user.id, object_id])
            mobile_upload_url = flask.url_for('.mobile_file_upload', object_id=object_id, token=token, _external=True)
            mobile_upload_qrcode = generate_qrcode(mobile_upload_url, should_cache=False)
        else:
            mobile_upload_url = None
            mobile_upload_qrcode = None
        object_url = flask.url_for('.object', object_id=object_id, _external=True)
        object_qrcode = generate_qrcode(object_url, should_cache=True)
        location_form = ObjectLocationAssignmentForm()
        (locations_map, locations_tree) = get_locations_tree()
        locations = [('-1', '—')]
        unvisited_location_ids_prefixes_and_subtrees = [(location_id, '', locations_tree[location_id]) for location_id in locations_tree]
        while unvisited_location_ids_prefixes_and_subtrees:
            (location_id, prefix, subtree) = unvisited_location_ids_prefixes_and_subtrees.pop(0)
            location = locations_map[location_id]
            locations.append((str(location_id), '{}{} (#{})'.format(prefix, get_translated_text(location.name), location.id)))
            for location_id in sorted(subtree, key=(lambda location_id: get_translated_text(locations_map[location_id].name)), reverse=True):
                unvisited_location_ids_prefixes_and_subtrees.insert(0, (location_id, '{}{} / '.format(prefix, get_translated_text(location.name)), subtree[location_id]))
        location_form.location.choices = locations
        possible_responsible_users = [('-1', '—')]
        for user in logic.users.get_users(exclude_hidden=True):
            possible_responsible_users.append((str(user.id), '{} (#{})'.format(user.name, user.id)))
        location_form.responsible_user.choices = possible_responsible_users
        measurement_actions = logic.action_translations.get_actions_with_translation_in_language(user_language_id, models.ActionType.MEASUREMENT, use_fallback=True)
        favorite_action_ids = logic.favorites.get_user_favorite_action_ids(flask_login.current_user.id)
        favorite_measurement_actions = [action for action in measurement_actions if ((action.id in favorite_action_ids) and (not action.is_hidden))]
        favorite_measurement_actions.sort(key=(lambda action: ((action.user.name.lower() if action.user else ''), (get_instrument_with_translation_in_language(action.instrument_id, user_language_id).translation.name.lower() if action.instrument else ''), action.translation.name.lower())))
        publication_form = ObjectPublicationForm()
        object_publications = logic.publications.get_publications_for_object(object_id=object.id)
        user_may_link_publication = (Permissions.WRITE in user_permissions)
        notebook_templates = get_notebook_templates(object_id=object.id, data=object.data, schema=object.schema, user_id=flask_login.current_user.id)
        linked_project = logic.projects.get_project_linked_to_object(object_id)
        object_languages = logic.languages.get_languages_in_object_data(object.data)
        languages = []
        for lang_code in object_languages:
            languages.append(get_language_by_lang_code(lang_code))
        all_languages = get_languages()
        metadata_language = flask.request.args.get('language', None)
        if (not any(((language.lang_code == metadata_language) for language in languages))):
            metadata_language = None
        return flask.render_template('objects/view/base.html', template_mode='view', show_object_type_and_id_on_object_page_text=get_user_settings(flask_login.current_user.id)['SHOW_OBJECT_TYPE_AND_ID_ON_OBJECT_PAGE'], show_object_title=get_user_settings(flask_login.current_user.id)['SHOW_OBJECT_TITLE'], measurement_type_name=logic.action_type_translations.get_action_type_translation_for_action_type_in_language(action_type_id=logic.actions.models.ActionType.MEASUREMENT, language_id=logic.languages.get_user_language(flask_login.current_user).id, use_fallback=True).name, metadata_language=metadata_language, languages=languages, all_languages=all_languages, SUPPORTED_LOCALES=logic.locale.SUPPORTED_LOCALES, ENGLISH=english, object_type=object_type, action=action, action_type=get_action_type_with_translation_in_language(action.type_id, user_language_id), instrument=instrument, schema=object.schema, data=object.data, object_log_entries=object_log_entries, ObjectLogEntryType=ObjectLogEntryType, last_edit_datetime=object.utc_datetime, last_edit_user=get_user(object.user_id), object_id=object_id, user_may_edit=user_may_edit, user_may_comment=user_may_edit, comments=comments.get_comments_for_object(object_id), comment_form=CommentForm(), files=logic.files.get_files_for_object(object_id), file_source_instrument_exists=False, file_source_jupyterhub_exists=False, file_form=FileForm(), external_link_form=ExternalLinkForm(), external_link_invalid=('invalid_link' in flask.request.args), mobile_upload_url=mobile_upload_url, mobile_upload_qrcode=mobile_upload_qrcode, notebook_templates=notebook_templates, object_qrcode=object_qrcode, object_url=object_url, restore_form=None, version_id=object.version_id, user_may_grant=user_may_grant, favorite_measurement_actions=favorite_measurement_actions, FileLogEntryType=FileLogEntryType, file_information_form=FileInformationForm(), file_hiding_form=FileHidingForm(), new_schema_available=new_schema_available, related_objects_tree=related_objects_tree, object_publications=object_publications, user_may_link_publication=user_may_link_publication, user_may_use_as_template=user_may_use_as_template, show_dataverse_export=show_dataverse_export, dataverse_url=dataverse_url, publication_form=publication_form, get_object=get_object, get_object_if_current_user_has_read_permissions=get_object_if_current_user_has_read_permissions, get_object_location_assignment=get_object_location_assignment, get_user=get_user, get_location=get_location, PAGE_SIZES=PAGE_SIZES, HORIZONTAL_LABEL_MARGIN=HORIZONTAL_LABEL_MARGIN, VERTICAL_LABEL_MARGIN=VERTICAL_LABEL_MARGIN, mm=mm, object_location_assignments=get_object_location_assignments(object_id), build_object_location_assignment_confirmation_url=build_object_location_assignment_confirmation_url, user_may_assign_location=user_may_edit, location_form=location_form, project=linked_project, get_project=get_project_if_it_exists, get_action_type=get_action_type, get_action_type_with_translation_in_language=get_action_type_with_translation_in_language, get_instrument_with_translation_in_language=get_instrument_with_translation_in_language)
    check_current_user_is_not_readonly()
    if (flask.request.args.get('mode', '') == 'upgrade'):
        should_upgrade_schema = True
    else:
        should_upgrade_schema = False
    return show_object_form(object, action=get_action(object.action_id), should_upgrade_schema=should_upgrade_schema)
@frontend.route('/objects/<int:object_id>', methods=['GET', 'POST'])
@object_permissions_required(Permissions.READ, on_unauthorized=on_unauthorized)
def object(object_id):
    object = get_object(object_id=object_id)
    related_objects_tree = logic.object_relationships.build_related_objects_tree(object_id, flask_login.current_user.id)
    user_language_id = get_user_language(flask_login.current_user).id
    english = get_language(Language.ENGLISH)
    object_languages = set()
    user_permissions = get_user_object_permissions(object_id=object_id, user_id=flask_login.current_user.id)
    user_may_edit = (Permissions.WRITE in user_permissions)
    user_may_grant = (Permissions.GRANT in user_permissions)
    user_may_use_as_template = (Permissions.READ in get_user_action_permissions(object.action_id, user_id=flask_login.current_user.id))
    action = get_action_with_translation_in_language(object.action_id, user_language_id, use_fallback=True)
    if (action.schema != object.schema):
        new_schema_available = True
    else:
        new_schema_available = False
    if ((not user_may_edit) and (flask.request.args.get('mode', ) == 'edit')):
        return flask.abort(403)
    if ((not user_may_edit) and (flask.request.args.get('mode', ) == 'upgrade')):
        return flask.abort(403)
    if (not flask.current_app.config['DISABLE_INLINE_EDIT']):
        if ((not user_may_edit) and (flask.request.args.get('mode', ) == 'inline_edit')):
            return flask.abort(403)
        if (user_may_edit and (flask.request.method == 'GET') and (flask.request.args.get('mode', ) in {, 'inline_edit'})):
            return show_inline_edit(object, get_action(object.action_id))
    if ((flask.request.method == 'GET') and (flask.request.args.get('mode', ) not in ('edit', 'upgrade'))):
        instrument = (get_instrument_with_translation_in_language(action.instrument_id, user_language_id) if action.instrument else None)
        object_type = get_action_type_with_translation_in_language(action_type_id=action.type_id, language_id=user_language_id).translation.object_name
        object_log_entries = object_log.get_object_log_entries(object_id=object_id, user_id=flask_login.current_user.id)
        dataverse_enabled = bool(flask.current_app.config['DATAVERSE_URL'])
        if dataverse_enabled:
            dataverse_url = logic.dataverse_export.get_dataverse_url(object_id)
            show_dataverse_export = (user_may_grant and (not dataverse_url))
        else:
            dataverse_url = None
            show_dataverse_export = False
        if user_may_edit:
            serializer = itsdangerous.URLSafeTimedSerializer(flask.current_app.config['SECRET_KEY'], salt='mobile-upload')
            token = serializer.dumps([flask_login.current_user.id, object_id])
            mobile_upload_url = flask.url_for('.mobile_file_upload', object_id=object_id, token=token, _external=True)
            mobile_upload_qrcode = generate_qrcode(mobile_upload_url, should_cache=False)
        else:
            mobile_upload_url = None
            mobile_upload_qrcode = None
        object_url = flask.url_for('.object', object_id=object_id, _external=True)
        object_qrcode = generate_qrcode(object_url, should_cache=True)
        location_form = ObjectLocationAssignmentForm()
        (locations_map, locations_tree) = get_locations_tree()
        locations = [('-1', '—')]
        unvisited_location_ids_prefixes_and_subtrees = [(location_id, , locations_tree[location_id]) for location_id in locations_tree]
        while unvisited_location_ids_prefixes_and_subtrees:
            (location_id, prefix, subtree) = unvisited_location_ids_prefixes_and_subtrees.pop(0)
            location = locations_map[location_id]
            locations.append((str(location_id), '{}{} (#{})'.format(prefix, get_translated_text(location.name), location.id)))
            for location_id in sorted(subtree, key=(lambda location_id: get_translated_text(locations_map[location_id].name)), reverse=True):
                unvisited_location_ids_prefixes_and_subtrees.insert(0, (location_id, '{}{} / '.format(prefix, get_translated_text(location.name)), subtree[location_id]))
        location_form.location.choices = locations
        possible_responsible_users = [('-1', '—')]
        for user in logic.users.get_users(exclude_hidden=True):
            possible_responsible_users.append((str(user.id), '{} (#{})'.format(user.name, user.id)))
        location_form.responsible_user.choices = possible_responsible_users
        measurement_actions = logic.action_translations.get_actions_with_translation_in_language(user_language_id, models.ActionType.MEASUREMENT, use_fallback=True)
        favorite_action_ids = logic.favorites.get_user_favorite_action_ids(flask_login.current_user.id)
        favorite_measurement_actions = [action for action in measurement_actions if ((action.id in favorite_action_ids) and (not action.is_hidden))]
        favorite_measurement_actions.sort(key=(lambda action: ((action.user.name.lower() if action.user else ), (get_instrument_with_translation_in_language(action.instrument_id, user_language_id).translation.name.lower() if action.instrument else ), action.translation.name.lower())))
        publication_form = ObjectPublicationForm()
        object_publications = logic.publications.get_publications_for_object(object_id=object.id)
        user_may_link_publication = (Permissions.WRITE in user_permissions)
        notebook_templates = get_notebook_templates(object_id=object.id, data=object.data, schema=object.schema, user_id=flask_login.current_user.id)
        linked_project = logic.projects.get_project_linked_to_object(object_id)
        object_languages = logic.languages.get_languages_in_object_data(object.data)
        languages = []
        for lang_code in object_languages:
            languages.append(get_language_by_lang_code(lang_code))
        all_languages = get_languages()
        metadata_language = flask.request.args.get('language', None)
        if (not any(((language.lang_code == metadata_language) for language in languages))):
            metadata_language = None
        return flask.render_template('objects/view/base.html', template_mode='view', show_object_type_and_id_on_object_page_text=get_user_settings(flask_login.current_user.id)['SHOW_OBJECT_TYPE_AND_ID_ON_OBJECT_PAGE'], show_object_title=get_user_settings(flask_login.current_user.id)['SHOW_OBJECT_TITLE'], measurement_type_name=logic.action_type_translations.get_action_type_translation_for_action_type_in_language(action_type_id=logic.actions.models.ActionType.MEASUREMENT, language_id=logic.languages.get_user_language(flask_login.current_user).id, use_fallback=True).name, metadata_language=metadata_language, languages=languages, all_languages=all_languages, SUPPORTED_LOCALES=logic.locale.SUPPORTED_LOCALES, ENGLISH=english, object_type=object_type, action=action, action_type=get_action_type_with_translation_in_language(action.type_id, user_language_id), instrument=instrument, schema=object.schema, data=object.data, object_log_entries=object_log_entries, ObjectLogEntryType=ObjectLogEntryType, last_edit_datetime=object.utc_datetime, last_edit_user=get_user(object.user_id), object_id=object_id, user_may_edit=user_may_edit, user_may_comment=user_may_edit, comments=comments.get_comments_for_object(object_id), comment_form=CommentForm(), files=logic.files.get_files_for_object(object_id), file_source_instrument_exists=False, file_source_jupyterhub_exists=False, file_form=FileForm(), external_link_form=ExternalLinkForm(), external_link_invalid=('invalid_link' in flask.request.args), mobile_upload_url=mobile_upload_url, mobile_upload_qrcode=mobile_upload_qrcode, notebook_templates=notebook_templates, object_qrcode=object_qrcode, object_url=object_url, restore_form=None, version_id=object.version_id, user_may_grant=user_may_grant, favorite_measurement_actions=favorite_measurement_actions, FileLogEntryType=FileLogEntryType, file_information_form=FileInformationForm(), file_hiding_form=FileHidingForm(), new_schema_available=new_schema_available, related_objects_tree=related_objects_tree, object_publications=object_publications, user_may_link_publication=user_may_link_publication, user_may_use_as_template=user_may_use_as_template, show_dataverse_export=show_dataverse_export, dataverse_url=dataverse_url, publication_form=publication_form, get_object=get_object, get_object_if_current_user_has_read_permissions=get_object_if_current_user_has_read_permissions, get_object_location_assignment=get_object_location_assignment, get_user=get_user, get_location=get_location, PAGE_SIZES=PAGE_SIZES, HORIZONTAL_LABEL_MARGIN=HORIZONTAL_LABEL_MARGIN, VERTICAL_LABEL_MARGIN=VERTICAL_LABEL_MARGIN, mm=mm, object_location_assignments=get_object_location_assignments(object_id), build_object_location_assignment_confirmation_url=build_object_location_assignment_confirmation_url, user_may_assign_location=user_may_edit, location_form=location_form, project=linked_project, get_project=get_project_if_it_exists, get_action_type=get_action_type, get_action_type_with_translation_in_language=get_action_type_with_translation_in_language, get_instrument_with_translation_in_language=get_instrument_with_translation_in_language)
    check_current_user_is_not_readonly()
    if (flask.request.args.get('mode', ) == 'upgrade'):
        should_upgrade_schema = True
    else:
        should_upgrade_schema = False
    return show_object_form(object, action=get_action(object.action_id), should_upgrade_schema=should_upgrade_schema)