mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-16 12:05:53 +00:00
* remove docker-sqlite file - Do not want to encourage use of sqlite * Add Caddyfile * Add default site URL to .env - Matches Caddyfile * Cleanup / simplify .env file * Remove dev nginx conf file * Further cleanup of .env file * Update docker-compose.yml - Use caddy image instead of nginx as proxy * Set max body size * gunicorn: enable external logging * Update file structure * Cleanup docker-compose file * Update docker/docker-compose.yml Co-authored-by: Matthias Mair <code@mjmair.com> * Update docker/Caddyfile Co-authored-by: Matthias Mair <code@mjmair.com> * Fix for postgresql packages - Need postgresql13-client to be installed, it contains pg_dump - Without this, backup / restore *does not work* * Create static_i18n dir if it does not exist * Reduce output from collectstatic * Revert gunicorn logging - Want to see the logs in docker * Fix trailing slash Ref: https://github.com/inventree/InvenTree/pull/6551#issuecomment-1962423765 * tasks.py - pass 'nouv' option through * Update package requirements: - Allow installation of rapidfuzz without building * Install uv as part of docker image * Add environment variable to control downstream URL * Do not use uv package manager by default - Currently does not work "correctly" - ignores installed packages - Requires further work to run reliably * Fix docker-compose file - Do not build locally * Cleanup gunicorn file - Remove unused lien * Cleanup docker-compose.yml - Simpler volume management * Update Caddyfile Add newline * Update requirements.txt Add newline * Update tasks.py Add missing blank line * Simplify Caddyfile * Adds option for customizing web port * cleanup docker-compose.yml - Better mapping of caddy data - Cleaner volume setup * Add django version template - Ensure all docs links point to the current django version we are using * docs: cleanup intro.md * Cleanup serving_files.md * Cleanup config.md * docker install docs updates * Enable code block copying * Fix include file * Fix link * Update docker install docs * Update docker.md * Add info about demo dataset * Tweak heading * Update docs link checks * Fix workflow * Another fix * More ignore pattearns --------- Co-authored-by: Matthias Mair <code@mjmair.com>
132 lines
4.2 KiB
Markdown
132 lines
4.2 KiB
Markdown
---
|
|
title: Model Metadata
|
|
---
|
|
|
|
## Model Metadata
|
|
|
|
Plugins have access to internal database models (such at [Parts](../../part/part.md)), and any associated data associated with these models. It may be the case that a particular plugin needs to store some extra information about a particular model instance, to be able to perform custom functionality.
|
|
|
|
One way of achieving this would be to create an entirely new database model to keep track of this information, using the [app plugin mixin](./app.md). However, this is a very heavy-handed (and complicated) approach!
|
|
|
|
A much simpler and more accessible method of recording custom information against a given model instance is provided "out of the box" - using *Model Metadata*.
|
|
|
|
### MetadataMixin Class
|
|
|
|
*Most* of the models in the InvenTree database inherit from the `MetadataMixin` class, which adds the `metadata` field to each inheriting model. The `metadata` field is a [JSONField]({% include "django.html" %}/ref/models/fields/#django.db.models.JSONField) which allows for storing arbitrary JSON data against the model instance.
|
|
|
|
This field is provided to allow any plugins to store and retrieve arbitrary data against any item in the database.
|
|
|
|
!!! tip "External Use Only"
|
|
It is important to note that the `metadata` field of each model instance is not used for any internal functionality. Any data stored against this field is only for use by external plugins.
|
|
|
|
## Accessing Metadata
|
|
|
|
### Plugin Access
|
|
|
|
The `metadata` field can be accessed and updated directly from custom plugin code, as follows:
|
|
|
|
```python
|
|
from part.models import Part
|
|
|
|
# Show metadata value against a particular Part instance
|
|
part = Part.objects.get(pk=100)
|
|
print(part.metadata)
|
|
|
|
> {'foo': 'bar'}
|
|
|
|
part.metadata['hello'] = 'world'
|
|
print(part.metadata)
|
|
|
|
> {'foo': 'bar', 'hello': 'world'}
|
|
```
|
|
|
|
### API Access
|
|
|
|
For models which provide this metadata field, access is also provided via the API. Append `/metadata/` to the detail endpoint for a particular model instance to access.
|
|
|
|
For example:
|
|
|
|
{% with id="metadata_api", url="plugin/model_metadata_api.png", description="Access model metadata via API", maxheight="400px" %}
|
|
{% include 'img.html' %}
|
|
{% endwith %}
|
|
|
|
#### PUT vs PATCH
|
|
|
|
An important note with regard to metadata access via the API is the behaviour of a `PUT` request vs a `PATCH` request. As demonstrated in the comparison below, a `PUT` request will *overwrite* existing data, while a `PATCH` request will *merge* with existing data.
|
|
|
|
**Initial Data:**
|
|
|
|
```json
|
|
{"foo": "bar", "hello": "world"}
|
|
```
|
|
|
|
**Payload:**
|
|
|
|
```json
|
|
{"xyz": "XYZ"}
|
|
```
|
|
|
|
**Result of PUT request:**
|
|
|
|
```json
|
|
{"xyz: XYZ"}
|
|
```
|
|
|
|
**Result of PATCH request:**
|
|
|
|
```json
|
|
{"foo": "bar", "hello": "world", "xyz": "XYZ"}
|
|
```
|
|
|
|
!!! danger "Take Care"
|
|
Take care when updating metadata via the API, especially when using a PUT request.
|
|
|
|
### Python API Access
|
|
|
|
The [Python API library](../../api/python/python.md) provides similar support for accessing model metadata. Use the `setMetadata` method to retrieve metadata information from the server:
|
|
|
|
```python
|
|
from inventree.api import InvenTreeAPI
|
|
from inventree.part import Part
|
|
|
|
api = InvenTreeAPI("http://localhost:8000", username="admin", password="inventree")
|
|
|
|
part = Part(api, pk=100)
|
|
|
|
print(part.getMetadata())
|
|
|
|
> {'foo': 'bar', 'hello': 'world'}
|
|
```
|
|
|
|
Metadata can be added directly here using the `setMetadata` method:
|
|
|
|
```python
|
|
part.setMetadata("abc", "xyz")
|
|
|
|
print(part.getMetadata())
|
|
|
|
> {'abc': 'xyz', 'foo': 'bar', 'hello': 'world'}
|
|
```
|
|
|
|
!!! tip "Merge vs Overwrite"
|
|
By default setting a metadata `key:value` pair will *merge* data in with existing data, by using a [PATCH request](#put-vs-patch).
|
|
|
|
To *overwrite* existing metadata, use the `overwrite=True` flag:
|
|
|
|
```python
|
|
part.setMetadata({"aaa": "ABC"}, overwrite=True)
|
|
|
|
print(part.getMetadata())
|
|
> {'aaa': 'ABC'}
|
|
```
|
|
|
|
## Considerations
|
|
|
|
### Data Keys
|
|
|
|
There is no guarantee that the data added to a particular model will *not* be overwritten by a different plugin. Your plugin should at least ensure that the data keys used are unique to the plugin, to ensure that they do not conflict with other plugins
|
|
|
|
### Structured Data
|
|
|
|
If you need to store data which is more "structured" than JSON objects, consider using the (more complex) [app mixin](../plugins/app.md) to develop custom database tables for your data.
|