Tagging System
To create and manage tags for categorizing bookmarks, use the BookmarkService to handle validation, persistence, and cascading updates across the system.
Creating a Tag
Create a new tag by passing a dictionary of attributes to BookmarkService.create_tag. This method validates the tag name against length constraints and reserved words before persisting it.
from app.services.bookmark_service import BookmarkService
from app.models.tag import TagColor
service = BookmarkService()
tag_data = {
"name": "Research",
"color": "blue", # Corresponds to TagColor.BLUE
"description": "Academic and work-related research"
}
tag, error = service.create_tag(tag_data)
if error:
print(f"Failed to create tag: {error}")
else:
print(f"Created tag: {tag.name} (ID: {tag.id})")
Tag Attributes and Colors
The Tag class (found in app/models/tag.py) includes several key attributes:
name: The display name. Must be unique and non-reserved.color: ATagColorenum value. Defaults toTagColor.GRAY.usage_count: An integer tracking how many bookmarks currently use this tag.id: An 8-character unique identifier generated automatically.
Available colors are defined in the TagColor enum:
class TagColor(Enum):
RED = "red"
BLUE = "blue"
GREEN = "green"
YELLOW = "yellow"
PURPLE = "purple"
GRAY = "gray"
Updating and Renaming Tags
Use BookmarkService.update_tag to modify an existing tag. This method ensures that name changes still adhere to validation rules.
update_data = {
"name": "Deep Research",
"color": "purple"
}
updated_tag, error = service.update_tag(tag.id, update_data)
if not error:
print(f"Updated tag name to: {updated_tag.name}")
Listing and Sorting Tags
The BookmarkService.list_tags method returns all tags. Because the Tag class implements the __lt__ dunder method, you can easily sort them alphabetically by name.
tags = service.list_tags()
# Sort tags alphabetically (case-insensitive)
for t in sorted(tags):
print(f"{t.name} - {t.usage_count} bookmarks")
Deleting Tags (Cascading)
When you delete a tag using BookmarkService.delete_tag, the service automatically removes that tag from every bookmark that uses it before deleting the tag itself.
# This removes the tag from all associated bookmarks and then deletes it
success = service.delete_tag(tag.id)
if success:
print("Tag deleted and removed from all bookmarks.")
Tracking Tag Usage
While the BookmarkService manages high-level operations, the Tag model provides methods to manually track how many bookmarks are using a specific tag.
# Increment usage when a bookmark is tagged
new_count = tag.increment_usage()
# Decrement usage when a tag is removed (clamped at 0)
new_count = tag.decrement_usage()
Troubleshooting and Constraints
When managing tags, keep the following constraints from app/models/_validators.py in mind:
- Reserved Names: You cannot name a tag
all,untagged,archived, ortrash. These are reserved for system filters. - Length Limits: Tag names must be between 1 and 50 characters long.
- Unique IDs: Tags use a truncated UUID (8 characters). If you are manually constructing tags from dictionaries, ensure the
idis handled correctly or let theTagconstructor generate one. - Color Validation: When updating via the service, the
colorstring must match one of the values in theTagColorenum, or aValueErrorwill be raised during theTagColor(data["color"])conversion.