In this article, you will learn how does work CODENERIX API.

Since all the operations between the front and back end are happening through JSON communication, it is easy to think there is a protocol behind all of that. In fact, there is a RESTful API based on JSON to manage everything that is happening inside CODENERIX.

Actually, not everything happens on JSON. Forms are rendered on the server side and verified on the user side, but you can also enable the RESTful API for those.

The explanations below are for public view. If you would like to use those with protected views (the ones requiring a logged-in user), read “CODENERIX Authentication System“.

There are several ways to make CODENERIX work fully as a REST service:

  • Any view can work as a REST service just by enabling the “json” attribute on that view:
    json = True

    GenCreate, GenUpdate, GenDetail, and GenDelete also support “json_details“, which will return extra information about field types, mandatory fields, and restrictions:
    json_details = True
  • Any GET request that specifies that it wants a JSON answer using “force_rest_api=1” as a GET parameter in the URL
  • Any POST request that includes a “json” parameter
  • In GenList, if method json_builder() exists.
  • Any request that includes an HTTP “X-HTTP-REST” header (this is the most comfortable way to use REST)
  • There are basic actions like GET operation on lists that will return JSON naturally

NOTES:

  • POST operations on forms will accept JSON but will answer with a rendered form, except that any of the above is in action.
  • Any request with an ‘x-requested-with‘ parameter set to ‘XMLHttpRequest‘ will be threaded as an XHR request and processed as it is, not as a REST request.

The basic actions you can perform on any URL are mostly based on the nature of that URL. We recommend exploring the XHR panel from your browser to understand what information provides what service.

Valid methods:

  • GenList:
    • GET: get the list of data
    • POST: works as “add“, “create“, or “new
  • GenDetail:
    • GET: get details from a register
    • PUT: works as an “edit” or “update” operation
    • DELETE: works as a “delete” operation
  • GenDelete:
    • POST: works as a “delete

Examples

For a table that looks like this:

GenList – GET

An empty GET over a GenList will return exactly that information: [ /geodata/continents ]

{
	"meta": {
		"getval": {},
		"username": "xxxxxxxx",
		"context": {},
		"url_media": "/media/",
		"url_static": "/static/",
		"page": 1,
		"pages": [1],
		"pages_to_bring": 1,
		"linkadd": true,
		"vtable": false,
		"export_excel": true,
		"export_name": "list",
		"ngincludes": {
			"table": "/static/codenerix/partials/table.html"
		},
		"linkedit": true,
		"show_details": true,
		"show_modal": false,
		"search_filter_button": false,
		"request": {
			"path_info": "/geodata/continents",
			"query_string": "authtoken=test&authuser=xxxxxxxx&string=test&force_rest_api=1"
		},
		"version": "0.1",
		"version_api": null,
		"gentranslate": {
			"Add": "A\u00f1adir",
			"Cancel": "Cancelar",
			"Change": "Cambiar",
			"CleanFilters": "Limpiar filtros",
			"Date": "Fecha",
			"Day": "D\u00eda",
			"Delete": "Borrar",
			"Done": "Hecho",
			"Download": "Descargar",
			"Edit": "Editar",
			"Error": "Error",
			"Filters": "Filtros",
			"Go_back": "Volver",
			"Hour": "Hora",
			"Month": "Mes",
			"Minute": "Minuto",
			"PageNumber": "N\u00famero de p\u00e1gina",
			"PleaseWait": "Por favor espere",
			"PrintExcel": "Imprimir en Excel",
			"Save": "Guardar",
			"Save_here": "Guardar aqu\u00ed",
			"Save_and_new": "Guardar y nuevo",
			"Reload": "Recargar",
			"RowsPerPage": "Filas por p\u00e1gina",
			"Search": "Buscar",
			"Second": "Segundo",
			"Time": "Hora",
			"View": "Ver",
			"Warning": "Atenci\u00f3n",
			"Year": "A\u00f1o",
			"registers": "registros"
		},
		"rowsperpage": 50,
		"rowsperpageallowed": {
			"All": "Todos"
		},
		"row_total": 8,
		"row_first": 1,
		"row_last": 8,
		"content_type": null
	},
	"filter": {
		"search": "",
		"date": null,
		"subfilters": [],
		"subfiltersC": [{
			"key": "code",
			"name": "C\u00f3digo",
			"kind": "input",
			"value": null
		}, {
			"key": "es__name",
			"name": "Nombre",
			"kind": "input",
			"value": null
		}]
	},
	"table": {
		"head": {
			"columns": [{
				"id": "code",
				"name": "C\u00f3digo",
				"align": null,
				"type": "CharField"
			}, {
				"id": "es__name",
				"name": "Nombre",
				"align": null,
				"type": "CharField"
			}],
			"ordering": {},
			"datetimeQ": null,
			"extra_fields": {
				"field_check": null,
				"field_delete": false
			}
		},
		"body": [{
			"pk": "1",
			"code": "Eu",
			"es__name": "Europa"
		}, {
			"pk": "2",
			"code": "As",
			"es__name": "Asia"
		}, {
			"pk": "3",
			"code": "Tc",
			"es__name": "Todos los continentes"
		}, {
			"pk": "5",
			"code": "AF",
			"es__name": "\u00c1frica"
		}, {
			"pk": "6",
			"code": "AN",
			"es__name": "Ant\u00e1rtida"
		}, {
			"pk": "7",
			"code": "OC",
			"es__name": "Ocean\u00eda"
		}, {
			"pk": "8",
			"code": "NA",
			"es__name": "Norteam\u00e9rica"
		}, {
			"pk": "9",
			"code": "SA",
			"es__name": "Sudam\u00e9rica"
		}],
		"header": null,
		"summary": null
	}
}

But you may decide to filter the result, and then you would send a request including a “json” parameter in the URL:

The “json” parameter in the URL will look like this: [ /geodata/continents?json=… ]
{
	"listid": 0,
	"search": "",
	"page": 1,
	"pages_to_bring": 1,
	"rowsperpage": 50,
	"filters": {
		"code": null,
		"en__name": "ame"
	},
	"ordering": {
		"en__name": 1
	},
	"year": null,
	"month": null,
	"day": null,
	"hour": null,
	"minute": null,
	"second": null,
	"context": {},
	"search_filter_button": true
}

And the answer would look like this:

{
	"meta": {
		"getval": true,
		"username": "xxxxxxxx",
		"context": {},
		"url_media": "/media/",
		"url_static": "/static/",
		"page": 1,
		"pages": [1],
		"pages_to_bring": 1,
		"linkadd": true,
		"vtable": false,
		"export_excel": true,
		"export_name": "list",
		"ngincludes": {
			"table": "/static/codenerix/partials/table.html"
		},
		"linkedit": true,
		"show_details": true,
		"show_modal": false,
		"search_filter_button": true,
		"request": {
			"path_info": "/geodata/continents",
			"query_string": "json=%7B%22listid%22:0,%22search%22:%22%22,%22page%22:1,%22pages_to_bring%22:1,%22rowsperpage%22:50,%22filters%22:%7B%22code%22:null,%22en__name%22:%22ame%22%7D,%22ordering%22:%7B%22en__name%22:1%7D,%22year%22:null,%22month%22:null,%22day%22:null,%22hour%22:null,%22minute%22:null,%22second%22:null,%22context%22:%7B%7D,%22search_filter_button%22:true%7D"
		},
		"gentranslate": {
			"Add": "A\u00f1adir",
			"Cancel": "Cancelar",
			"Change": "Cambiar",
			"CleanFilters": "Limpiar filtros",
			"Date": "Fecha",
			"Day": "D\u00eda",
			"Delete": "Borrar",
			"Done": "Hecho",
			"Download": "Descargar",
			"Edit": "Editar",
			"Error": "Error",
			"Filters": "Filtros",
			"Go_back": "Volver",
			"Hour": "Hora",
			"Month": "Mes",
			"Minute": "Minuto",
			"PageNumber": "N\u00famero de p\u00e1gina",
			"PleaseWait": "Por favor espere",
			"PrintExcel": "Imprimir en Excel",
			"Save": "Guardar",
			"Save_here": "Guardar aqu\u00ed",
			"Save_and_new": "Guardar y nuevo",
			"Reload": "Recargar",
			"RowsPerPage": "Filas por p\u00e1gina",
			"Search": "Buscar",
			"Second": "Segundo",
			"Time": "Hora",
			"View": "Ver",
			"Warning": "Atenci\u00f3n",
			"Year": "A\u00f1o",
			"registers": "registros"
		},
		"rowsperpage": 50,
		"rowsperpageallowed": {
			"All": "All"
		},
		"row_total": 2,
		"row_first": 1,
		"row_last": 2,
		"content_type": null
	},
	"filter": {
		"search": "",
		"date": null,
		"subfilters": [],
		"subfiltersC": [{
			"key": "code",
			"name": "Code",
			"kind": "input",
			"value": null
		}, {
			"key": "en__name",
			"name": "Name",
			"kind": "input",
			"value": "ame"
		}]
	},
	"table": {
		"head": {
			"columns": [{
				"id": "code",
				"name": "Code",
				"align": null,
				"type": "CharField"
			}, {
				"id": "en__name",
				"name": "Name",
				"align": null,
				"type": "CharField"
			}],
			"ordering": {
				"en__name": 1
			},
			"datetimeQ": null,
			"extra_fields": {
				"field_check": null,
				"field_delete": false
			}
		},
		"body": [{
			"pk": "8",
			"code": "NA",
			"en__name": "North America"
		}, {
			"pk": "9",
			"code": "SA",
			"en__name": "South America"
		}],
		"header": null,
		"summary": null
	}
}

GenDetail – GET

A basic GET over a register with no parameters in the URL: [ /geodata/continents/5 ]

{
	"meta": {
		"gentranslate": {
			"Add": "Añadir",
			"Cancel": "Cancelar",
			"Change": "Cambiar",
			"CleanFilters": "Limpiar filtros",
			"Date": "Fecha",
			"Day": "Día",
			"Delete": "Borrar",
			"Done": "Hecho",
			"Download": "Descargar",
			"Edit": "Editar",
			"Error": "Error",
			"Filters": "Filtros",
			"Go_back": "Volver",
			"Hour": "Hora",
			"Month": "Mes",
			"Minute": "Minuto",
			"PageNumber": "Número de página",
			"PleaseWait": "Por favor espere",
			"PrintExcel": "Imprimir en Excel",
			"Save": "Guardar",
			"Save_here": "Guardar aquí",
			"Save_and_new": "Guardar y nuevo",
			"Reload": "Recargar",
			"RowsPerPage": "Filas por página",
			"Search": "Buscar",
			"Second": "Segundo",
			"Time": "Hora",
			"View": "Ver",
			"Warning": "Atención",
			"Year": "Año",
			"registers": "registros"
		},
		"linkedit": true,
		"linkdelete": true,
		"linkback": true,
		"cannot_delete": null,
		"cannot_update": null,
		"extra_context": {
			"no_render_as_foreign": [],
			"user": "xxxxxxxx",
			"ws_entry_point": "geodata/continents",
			"static_partial_row": "/static/codenerix/partials/rows.html",
			"static_partial_header": null,
			"static_partial_summary": "/static/codenerix/partials/summary.html",
			"static_app_row": "/static/codenerix/js/app.js",
			"static_controllers_row": null,
			"static_filters_row": "/static/codenerix/js/rows.js",
			"field_delete": false,
			"field_check": null,
			"extends_base": "base/base.html",
			"tabs_js": "[]",
			"is_modal_window": false,
			"tabs_autorender": []
		}
	},
	"body": {
		"code": "AF",
		"es__name": "África"
	}
}

GenAdd – GET

A basic GET to add a new element with authjson_details enabled:
[ /geodata/continents/add?authtoken=…&authuser=….&json={}&force_rest_api=1&authjson_details=1 ]

{
	"head": {
		"bound": false,
		"groups": [
			[
				"Details",
				12,
				[
					"code",
					6
				]
			]
		],
		"form_name": "AF8Q903HFSO8RZB"
	},
	"meta": {
		"version": "0.1",
		"version_api": null
	},
	"body": {
		"code": {
			"for": "id_GeoContinentForm_code",
			"type": "char",
			"html_name": "GeoContinentForm_code",
			"value": "",
			"label": "Code",
			"notes": [
				"This field is required.",
				"Ensure this value has at most 2 characters"
			],
			"limits": {
				"max_length": 2,
				"required": true
			}
		},
		"name": {
			"for": "id_ContinentTextFormEN_name",
			"type": "char",
			"html_name": "ContinentTextFormEN_name",
			"value": "",
			"label": "Name",
			"notes": [
				"This field is required.",
				"Ensure this value has at most 100 characters"
			],
			"limits": {
				"max_length": 100,
				"required": true
			}
		}
	}
}

Final

For any questions you may have about the RESTful API, check your browser for extra information and check out how CODENERIX is doing under the hood.