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

Since all the operations between the front-end and the 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 enable the RESTful API as well for those.

The explanations below are for public views, if you would like to use those with protected views (the ones that require a logged-in user) make sure to read “CODENERIX Authentication System“.

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

  • Any view can work as a REST service just 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 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 that includes an ‘x-requested-with‘ parameter set to ‘XMLHttpRequest‘ will be threaded as an XHR request and will be processed as it, 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 pannel from your browser to understand what information is providing 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, 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.