Tagging and Visual Labeling
To categorize bookmarks in this system, you use the Tag model and manage it through the BookmarkService. Tags include visual color presets and metadata like descriptions and usage counts.
Creating and Managing Tags
The recommended way to create and update tags is through the BookmarkService, which handles validation and persistence.
from app.services.bookmark_service import BookmarkService
from app.models.tag import TagColor
service = BookmarkService()
# Create a new tag
tag_data = {
"name": "Research",
"color": "blue",
"description": "Academic and professional research"
}
tag, error = service.create_tag(tag_data)
if error:
print(f"Failed to create tag: {error}")
else:
print(f"Created tag: {tag.name} with ID: {tag.id}")
# Update an existing tag
update_data = {"color": "purple", "name": "Deep Research"}
updated_tag, error = service.update_tag(tag.id, update_data)
Visual Labeling with TagColor
The TagColor enum provides a set of preset colors for UI rendering. If no color is provided during creation, it defaults to TagColor.GRAY.
Available colors in app.models.tag.TagColor:
RED("red")BLUE("blue")GREEN("green")YELLOW("yellow")PURPLE("purple")GRAY("gray")
You can assign these colors directly or via their string values when using from_dict:
from app.models.tag import Tag, TagColor
# Direct assignment
tag = Tag(name="Urgent", color=TagColor.RED)
# Assignment via dictionary (used by BookmarkService)
tag_json = {"name": "Work", "color": "green"}
work_tag = Tag.from_dict(tag_json)
Validation Rules
The Tag model and BookmarkService enforce specific rules for tag names:
- Non-empty: Tag names cannot be empty or just whitespace.
- Length: Tag names cannot exceed 50 characters.
- Normalization: The
_normalize_name()method is used internally to strip whitespace and lowercase names for uniqueness checks.
If you attempt to rename a tag to an invalid name, the rename() method will raise a ValueError:
tag = Tag(name="Valid")
try:
tag.rename("") # Raises ValueError: Tag name cannot be empty
except ValueError as e:
print(e)
try:
tag.rename("A" * 51) # Raises ValueError: Tag name cannot exceed 50 characters
except ValueError as e:
print(e)
Tracking Tag Usage
The Tag model includes a usage_count attribute and methods to track how many bookmarks are associated with it.
[!WARNING] The
BookmarkServicedoes not currently automate usage count tracking. You must manually callincrement_usage()ordecrement_usage()when adding or removing tags from bookmarks to keep this count accurate.
tag = Tag(name="Python")
# Manually increment when a bookmark is tagged
tag.increment_usage()
print(tag.usage_count) # Output: 1
# Manually decrement when a tag is removed
tag.decrement_usage()
print(tag.usage_count) # Output: 0
Deleting Tags and Cascading Cleanup
When you delete a tag using BookmarkService.delete_tag(tag_id), the service automatically performs a cleanup by removing that tag ID from all bookmarks that were using it.
# This will:
# 1. Find all bookmarks containing this tag ID
# 2. Remove the tag ID from those bookmarks
# 3. Save the updated bookmarks and invalidate their cache
# 4. Delete the tag from the repository
success = service.delete_tag("tag_id_123")
This ensures that bookmarks do not retain references to non-existent tags.