Ejemplo: agregar un controlador

Crear el controlador

from geonode.metadata.handlers.abstract import MetadataHandler

class MySchemaHandler(MetadataHandler):
   pass

Registre su controlador, para que el administrador de metadatos lo sepa:

from geonode.metadata.manager import metadata_manager

metadata_manager.add_handler("myhandler", MySchemaHandler)

Crear esquema esqueleto

Para definir varios campos, puede resultar útil crear un esquema esqueleto y agregar los campos uno por uno.

Este es un archivo esqueleto de muestra myproject.json:

{
  "p1_short_name": {
    "type": ["string", "null"],
    "minLength": 1,
    "maxLength": 255,
    "geonode:after": "title",
    "geonode:handler": "sparse"
  },

  "edition": {
  "type": "object",
  "properties": {
    "id": {"type": "string"},
    "label": {"type": "string"}
  },
    "geonode:handler": "myhandler"
    "geonode:thesaurus": "p1_edition_codelist"
  }
}
p1_nombre_corto:

Este es un campo completamente nuevo, manejado por SparseHandler, por lo que no queremos manejarlo en YourSchemaHandler.Deberá estar registrado como SparseField.

edición:

This field is declared into GeoNode as a field handled by the BaseHandler. We are telling the manager that we want to handle it via the YourSchemaHandler. Also, we are defining it to be a codelist populated via the «p1_edition_codelist» thesaurus, that shall be created. Since we are declaring a new Handler for this field, we’ll need the logic to handle it.

Registrar campos dispersos

Es posible que desees registrar tus cosas al iniciar tu aplicación:

def load_schema_file():
    with open(os.path.join(os.path.dirname(__file__), "schemas", "myproject.json")) as f:
        schema_file = json.load(f)

    return schema_file


def init():

    # register sparse fields:
    for property_name, subschema in load_schema_file().items():
        if subschema.get("geonode:handler", None) == "sparse":
            sparse_field_registry.register(property_name, subschema)

    metadata_manager.add_handler("myhandler", YourSchemaHandler)

Generar esquema

Luego, debes implementar el método Handler que inicializa su parte del equema (update_schema)

def update_schema(self, jsonschema, context, lang=None):

    schema_file = load_schema_file()

    # building the full schema using the external file
    for property_name, subschema in schema_file.items():

        # tries to set up "title" and "description"
        self._localize_subschema_labels(context, subschema, lang, property_name)

        if "geonode:handler" not in subschema:
            # set the default handler if not specified
            subschema.update({"geonode:handler": "myhandler"})
        else:
            # skip fields that have already been added to the sparsefield register
            if subschema.get("geonode:handler", None) == "sparse":
                continue

        # add this field's subschema to the full jsonschema
        self._add_subschema(jsonschema, property_name, subschema)

Ahora, dado que tomamos el control del campo de edition necesitamos implementar los métodos que implementan

  • la transformación de modelo a jsonschema (get_jsonschema_instance)

  • la transformación jsonschema-to-model (update_resource)

Handle content

Necesitamos decidir qué se almacenará en el campo edición.

Los campos vinculados a los tesauros se dictan con las claves id y label, como también se documenta en el esquema definido anteriormente.

Queremos guardar en el campo edición (que está definido en ResourceBase como un campo de texto) alguna información legible;usemos la etiqueta predeterminada de ThesaurusKeyword.En este tesauro, no defina ninguna etiqueta localizada para asegurarse de obtener la etiqueta predeterminada como etiqueta.

Cuando se devuelve la instancia de jsonschema, debemos proporcionar el par (id, etiqueta) de todos modos.Podemos recuperar KeywordLabel filtrando por la etiqueta predeterminada, asumiendo que no hay duplicados.Puede haber otras advertencias, pero supongamos que está bien para el ejemplo.

Modelo a jsonschema

Busquemos la palabra clave del diccionario de sinónimos con la etiqueta predeterminada dada y creemos el objeto de retorno:

def get_jsonschema_instance(
    self, resource: ResourceBase, field_name: str, context: dict, errors: dict, lang: str = None
):
    match field_name:
        case "edition":
            if resource.edition:
                    if tl := ThesaurusLabel.objects.filter(alt_label=resource.edition).first()
                            return {"id": tl.pk, "label": resource.edition}
            return {}
        case _:
            raise Exception(f"Unhandled field {field_name}")

jsonschema-to-modelo

La instancia de jsonschema, si existe, sigue siendo un dict con las claves «id» y «label»;solo devolveremos la etiqueta:

def update_resource(
    self, resource, field_name, json_instance, context, errors, **kwargs
):
    field_value = json_instance.get(field_name, {})
    match field_name:
        case "edition":
            resource.edition = field_value.get("label", None)
        case _:
            raise Exception(f"Unhandled field {field_name}")