Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

References/Favorites: Difference between revisions

From OHC Network Wiki
Content deleted Content added
OHC identity seed
 
Add Navbox platform (via update-page on MediaWiki MCP Server)
 
Line 214: Line 214:
* The list is capped at <code>settings.MAX_FAVORITES_PER_LIST</code> (env <code>MAX_FAVORITES_PER_LIST</code>, default <code>50</code>). <code>add_favorite</code> drops the oldest entries beyond the cap.
* The list is capped at <code>settings.MAX_FAVORITES_PER_LIST</code> (env <code>MAX_FAVORITES_PER_LIST</code>, default <code>50</code>). <code>add_favorite</code> drops the oldest entries beyond the cap.
* Never set the <code>user_favorites_lists:*</code> or <code>user_favorites_list_object:*</code> cache keys from a client. <code>save()</code> / <code>refresh_cache()</code> maintain them, and <code>remove_favorite</code> tears them down when a list empties.
* Never set the <code>user_favorites_lists:*</code> or <code>user_favorites_list_object:*</code> cache keys from a client. <code>save()</code> / <code>refresh_cache()</code> maintain them, and <code>remove_favorite</code> tears them down when a list empties.

{{Navbox platform}}


{{Related}}
{{Related}}

Latest revision as of 09:55, 6 July 2026

referenceplatformCARE 3.0+

UserResourceFavorites lets a user pin resource IDs into named lists so the owning resource's list endpoint can surface them first. It's a Care-internal personalization feature, not a FHIR resource — you touch it when you add favoriting to a resource's UI.

Each list is scoped by a resource_type and, optionally, a facility. There's no EMRResource serialize/de_serialize spec here. The moving parts are an enum (FavoriteResourceChoices), a default-list constant, a DRF filter backend (FavoritesFilter), and a viewset mixin (EMRFavoritesMixin) that wires up the read/write endpoints.

Source:

Models

Model Purpose
UserResourceFavorites Stores a per-user, named list of favorited resource integer PKs, optionally scoped to a facility and constrained to one resource type

UserResourceFavorites extends EMRBaseModel, which supplies external_id, the audit fields created_by / updated_by / created_date / modified_date, and soft-delete semantics.

UserResourceFavorites fields

Field Type Required Default Notes
user FK → User optional
favorites ArrayField(IntegerField) yes
favorite_list CharField(255) yes
resource_type CharField(255) yes
facility FK → Facility optional

The tuple (user, resource_type, facility, favorite_list) addresses a single row: it's what the cache keys and the get_or_create in add_favorite are built from.

resource_type values — FavoriteResourceChoices

The API constrains resource_type to the string values of FavoriteResourceChoices (care/emr/resources/favorites/spec.py). Each viewset binds to exactly one value through its FAVORITE_RESOURCE attribute.

Value Bound resource Wired viewset
activity_definition [[References/Activity Definition Activity definition]]
charge_item_definition [[References/Charge Item Definition Charge item definition]]
product_knowledge [[References/Product Knowledge Product knowledge]]
observation_definition [[References/Observation Definition Observation definition]]
questionnaire References/Questionnaire QuestionnaireViewSet
facility_organization References/Organization (facility org) FacilityOrganizationViewSet

Resource specs (API schema)

Favorites skip the EMRResource Create/Update/List/Retrieve pattern. The spec surface is just:

Symbol Kind Role
FavoriteResourceChoices str, Enum (spec.py) Allowed resource_type values (table above). A viewset selects one via FAVORITE_RESOURCE = FavoriteResourceChoices.<x>.value
DEFAULT_FAVORITE_LIST constant (spec.py) "default" — the list name used when the request omits favorite_list
FavoriteRequest pydantic.BaseModel (viewset) Request body for write actions. One field: favorite_list: str = DEFAULT_FAVORITE_LIST
FavoritesFilter DRF BaseFilterBackend (filters.py) Read path. Adds the favorite_list query param to the resource's list endpoint and restricts/orders results to that user's favorites
EMRFavoritesMixin viewset mixin (api/viewsets/favorites.py) Adds the favorite_lists, add_favorite, remove_favorite actions

FavoriteRequest

Field Type Required Default
favorite_list str optional "default" (DEFAULT_FAVORITE_LIST)

Favorited objects have no read schema of their own. They come back through the owning resource's list endpoint — for example, the questionnaire list serializer — filtered and ordered by FavoritesFilter. The favorite_lists action returns only {"lists": [<list name>, ...]}.

  • User — owner of every favorites row (user FK)
  • Facility — optional scope (facility FK); null = instance-wide
  • Each resource_type binds to one favoritable resource — see the FavoriteResourceChoices table

Methods & save behaviour

Every row is mirrored into a Django cache, kept in sync by save() and refresh_cache().

Cache keys

Two module-level helpers build the keys, encoding a missing facility as -:

favorite_lists_cache_key(user, resource_type, facility)
  → "user_favorites_lists:{user.id}:{resource_type}:{facility.id|-}"

favorite_list_object_cache_key(user, resource_type, facility, favorite_list)
  → "user_favorites_list_object:{user.id}:{resource_type}:{facility.id|-}:{favorite_list}"
  • The lists key holds the ordered, deduplicated set of favorite_list names a user has for a (resource_type, facility).
  • The list-object key holds the favorites integer array for one named list.

refresh_cache(refresh_list=False)

  • Always writes the current favorites array under the list-object key.
  • With refresh_list=True, also recomputes the deduplicated, modified_date-descending set of favorite_list names for the (user, resource_type, facility) and writes it under the lists key.

save() side effects

save() sets refresh_list = not self.pk (true only on insert), calls super().save(), then refresh_cache(refresh_list=refresh_list). So:

  1. Creating a new list refreshes both the lists cache and the list-object cache.
  2. Updating an existing list refreshes only the list-object cache — the set of list names hasn't changed.

Treat these keys as platform-maintained. Write through the model or the endpoints so the cache stays consistent.

API integration notes

There's no standalone favorites endpoint. Favorites ride on the owning resource's viewset through EMRFavoritesMixin. A viewset opts in by mixing in EMRFavoritesMixin, setting FAVORITE_RESOURCE, and adding FavoritesFilter to filter_backends:

class QuestionnaireViewSet(EMRModelViewSet, EMRFavoritesMixin):
    filter_backends = [filters.DjangoFilterBackend, FavoritesFilter]
    FAVORITE_RESOURCE = FavoriteResourceChoices.questionnaire.value

Endpoints (relative to the owning resource)

Action Method · route Body Behaviour
add_favorite POST {resource}/{id}/add_favorite/ FavoriteRequest get_or_create the (user, favorite_list, resource_type, facility) row, insert(0, obj.id) (newest-first), dedupe, trim to MAX_FAVORITES_PER_LIST, save. Returns {}
remove_favorite POST {resource}/{id}/remove_favorite/ FavoriteRequest Pops obj.id from the list. Emptying the list deletes the row and both cache keys. 404/validation error if the list does not exist. Returns {}
favorite_lists GET {resource}/favorite_lists/ Returns {"lists": [<name>, ...]} (cache-first, falls back to DB). Resolves facility from the facility_external_id kwarg or ?facility= query param
list (filtered) GET {resource}/?favorite_list=<name> FavoritesFilter restricts the resource list to id__in=favorites and orders by favorite position (sort_index). Empty/unknown list → empty queryset

What's server-maintained or validated:

  • resource_type is never client-supplied — each viewset fixes it via FAVORITE_RESOURCE. The client only sends favorite_list.
  • facility is derived server-side via retrieve_facility_obj(obj) (defaulting to obj.facility), so favorites inherit the favorited object's facility scope. A null facility is an instance-wide list; a set one is facility-scoped.
  • favorites holds integer primary keys, not external_ids. Order is newest-first; add_favorite re-inserts at position 0 and dedupes.
  • The list is capped at settings.MAX_FAVORITES_PER_LIST (env MAX_FAVORITES_PER_LIST, default 50). add_favorite drops the oldest entries beyond the cap.
  • Never set the user_favorites_lists:* or user_favorites_list_object:* cache keys from a client. save() / refresh_cache() maintain them, and remove_favorite tears them down when a list empties.