We can either create a definition from scratch, or create one based on an existing definition. We'll start with the completely new one, and then we'll create a second definition based on the first. Let's assume all the necessary classes and fields already exist.
We'll use the API connector we built previously in Create an API connector. We could simplify this by using the 'official' Unicat client lib, but that wouldn't give the API insights because it is more high-level.
Note: at the end of the page, we show the same example while using the Unicat client lib.
We will build an 'article' definition first. This is a two-step process: create, then commit. We can't use it if it isn't committed yet.
The article definition will have three classes - an article class (containing fields for e.g. article number, GTIN, description, images), an internet class (containing meta information like meta title, meta description, meta keywords), and an ERP class (with price, packing, stock fields)
Let's start with some setup - connecting to the Unicat API and finding the classes we're looking for.
from ccapi import UnicatApi
import keyring
secret_api_key = keyring.get_password("unicat-my-project", "my-key-name")
ccapi = UnicatApi("https://unicat.app", "<project gid>")
success, result = ccapi.connect(secret_api_key)
classes = []
for class_gid, class_ in ccapi.data["classes"].items():
if class_["name"] in ("article", "meta", "erp"):
classes.append(class_gid)
titlefield = None
for field_gid, field in ccapi.data["fields"].items():
if field["name"] == "artnr":
titlefield = field_gid
After a successful connection, we already have all predefined definitions, classes, and fields, so we can enumerate them to find the ones we need by name. We know that the 'artnr' field is a part of the 'article' class so we don't do the extra checks here.
To create the definition, we refer to the definitions/create documentation first, and then we write the code.
data = {
"name": "article",
"label": {"en": "Article", "nl": "Artikel"},
"classes": classes,
"titlefield": titlefield,
}
success, result = ccapi.call("/definitions/create", data)
definition = ccapi.data["definitions"][result["definition"]]
We now have a new definition, but we cannot use it yet because it is still a sort of working copy; it needs to be committed first. Until we do that, we can keep modifying this new definition (definitions/modify).
Let's add the final commit step based on the definitions/commit documentation
success, result = ccapi.call("/definitions/commit", {"definition": definition["gid"]})
definition = ccapi.data["definitions"][result["definition"]]
We update our local 'definition' variable with the latest data returned from the commit call.
Note: read the background information in updating definitions first
Some but not all articles are accessories for other articles - we want a separate definition to reflect this. We'll name it 'article_accessory'.
Let's start from the top again, connect using the ccapi and find what we need:
from ccapi import UnicatApi
import keyring
secret_api_key = keyring.get_password("unicat-my-project", "my-key-name")
ccapi = UnicatApi("https://unicat.app", "<project gid>")
success, result = ccapi.connect(secret_api_key)
article_definition = None
for definition_gid, definition in ccapi.data["definitions"].items():
if definition["name"] == "article":
article_definition = definition_gid
accessory_field = None
for field_gid, field in ccapi.data["fields"].items():
if field["name"] == "for_model":
accessory_field = field_gid
To get our article_accessory definition, we modify the article definition by adding the for_model field (see definitions/fields/add).
data = {
"definition": article_definition,
"field": accessory_field,
}
success, result = ccapi.call("/definitions/fields/add", data)
working_copy = ccapi.data["definitions"][result["definition"]]
We got a working copy back - this one has a different gid from the original article_definition, and subsequent changes should be done on this working copy.
Let's rename the working copy and update the label too.
data = {
"definition": working_copy["gid"],
"name": "article_accessory",
"label": {"en": "Article - accessory", "nl": "Artikel - accessoire"},
}
success, result = ccapi.call("/definitions/modify", data)
working_copy = ccapi.data["definitions"][result["definition"]]
Now, we don't want to update the original, we want a new definition, so we'll be using the definitions/save_as_new API call.
data = {
"definition": working_copy["gid"],
}
success, result = ccapi.call("/definitions/save_as_new", data)
accessory_definition = ccapi.data["definitions"][result["definition"]]
pip install unicat
Ok, here it goes:
from unicat import Unicat
from .config import PROJECT_GID, SECRET_API_KEY, LOCAL_ASSET_FOLDER
unicat = Unicat("https://unicat.app", PROJECT_GID, SECRET_API_KEY, LOCAL_ASSET_FOLDER)
if not unicat.connect():
raise Exception("Invalid connection settings")
# Create a new definition from scratch
classes = unicat.get_classes_by_name(["article", "meta", "erp"])
titlefield = unicat.get_field_by_name("artnr")
definition = unicat.mutate.create_definition(
name = "article",
label = {"en": "Article", "nl": "Artikel"},
classes = classes,
titlefield = titlefield
)
definition = unicat.mutate.commit_definition(definition)
# Create a definition based on an existing one
accessoryfield = unicat.get_field_by_name("for_model")
fields = definition.fields
fields.append(accessoryfield)
working_copy = unicat.mutate.modify_definition(
definition
name = "article_accessory",
label = {"en": "Article - accessory", "nl": "Artikel - accessoire"},
# classes remain unchanged, fields are changed:
fields = fields,
)
accessory_definition = unicat.mutate.save_as_new_definition(working_copy)