# User Data Cookbook

Manage user-generated fixtures from the Django admin to keep audit trails, share reproducible scenarios, and seed fresh environments with known records.

- [Access points](#access-points)
- [Exploring user data sections](#exploring-user-data-sections)
- [Exporting user data](#exporting-user-data)
- [Importing user data](#importing-user-data)
- [Marking objects as user data](#marking-objects-as-user-data)
- [Troubleshooting](#troubleshooting)

## Access points

1. Sign in to the Django admin and open the home dashboard.
2. Select **User Data** from the header shortcuts (the button routes to the `admin:user_data` view defined in [`apps/locals/user_data.py`](../../apps/locals/user_data.py)).
3. The data list view renders the template [`apps/locals/templates/admin/data_list.html`](../../apps/locals/templates/admin/data_list.html), providing a searchable table of exported fixtures grouped by app and model.

Use the filter field at the top of the table to narrow the list by any fragment of the app name, model name, or entity label. The table updates instantly without a full page refresh.

## Exploring user data sections

The view assembles sections for every model that exposes the `is_user_data` flag (`apps/locals/user_data.py` lines 680-734). Each entry shows:

- **App** – The Django app label (for example `core`).
- **Model** – The verbose name of the concrete model (for example `RFID tag`).
- **Entity** – A hyperlink to the change form for the specific object.
- **Fixture** – The filename written on disk for the exported JSON fixture.

If no records are currently flagged as user data, the view displays “None available”.

## Exporting user data

Click **Export** above the table to download a ZIP archive that contains every recorded user datum. The archive is generated by `_user_data_export` in [`apps/locals/user_data.py`](../../apps/locals/user_data.py) and includes one JSON fixture per object.

- The exported filename follows the pattern `user_data_<user-id>.zip` so you can track who generated the bundle.
- Fixtures are sourced from the per-user directory created by `_data_dir` in [`apps/locals/user_data.py`](../../apps/locals/user_data.py).
- Existing fixtures in the archive are overwritten when you export again, ensuring the latest changes are captured.

## Importing user data

To restore user data into another environment:

1. Click **Import** next to the export link.
2. Choose a ZIP archive generated by the export flow (the upload form accepts `.zip` files only).
3. Submit the form to invoke `_user_data_import` in [`apps/locals/user_data.py`](../../apps/locals/user_data.py).

The import process loads each fixture and, when available, re-applies the `is_user_data` flag (see `_load_fixture` in [`apps/locals/user_data.py`](../../apps/locals/user_data.py)). Successful imports redirect back to the list view with the updated objects.

## Marking objects as user data

Several admin surfaces let you toggle whether an object should be captured as user data:

- **List actions** – Models such as RFID tags expose the `Toggle selected User Data` bulk action in the Django admin (`apps/core/admin.py` lines 3026-3055).
- **Favorites interface** – The favorites dashboard supports tagging shortcuts as user data via checkboxes (`apps/locals/templates/admin/favorite_list.html`).
- **Change forms** – When an object is edited through a custom form that includes the `is_user_data` switch, saving the change updates the fixture immediately (`apps/core/admin.py` lines 1857-1902).

When enabled, Arthexis writes a JSON fixture next to other managed data in `data/<username>/`. Disabling user data removes the fixture, and the entry disappears from the list after the next refresh.

## Troubleshooting

- **The export link downloads an empty archive** – Confirm that at least one object has `is_user_data=True`. You can verify this on the object change form or by checking the favorites list.
- **Cannot toggle user data** – Some users are restricted from storing fixtures. The helper `_user_allows_user_data` (line 43) blocks toggles for profiles without permission. Use a service or admin account to perform the action, or delegate through the `operate_as` relationship.
- **Import skips records** – The importer validates JSON payloads before loading them. Review the Django messages displayed after import for warnings about missing models or stale primary keys.
