Performing Bookmark CRUD Operations
To perform CRUD (Create, Read, Update, Delete) operations on bookmarks in this project, you use the BookmarkRepository class. This repository provides an in-memory data store that abstracts the underlying storage logic for bookmarks, tags, and collections.
Creating and Updating Bookmarks
The save_bookmark method handles both the initial creation of a bookmark and any subsequent updates. Since the repository uses the bookmark's id as a key, calling save_bookmark with an existing ID will overwrite the previous entry.
from app.db.repository import BookmarkRepository
from app.models.bookmark import Bookmark
repo = BookmarkRepository()
# 1. Create a new bookmark
new_bookmark = Bookmark(
url="https://github.com/vik-advani",
title="Vik Advani GitHub",
description="Project repository"
)
repo.save_bookmark(new_bookmark)
# 2. Update an existing bookmark
new_bookmark.title = "Updated Title"
new_bookmark.add_tag("dev-tools")
repo.save_bookmark(new_bookmark)
Retrieving Bookmarks
You can retrieve a single bookmark by its unique ID or fetch a paginated list with optional status filtering.
Single Lookup
Use get_bookmark to retrieve a specific instance. It returns None if the ID is not found.
bookmark = repo.get_bookmark("some-id-123")
if bookmark:
print(f"Found: {bookmark.title}")
Paginated Listing and Filtering
The list_bookmarks method returns a tuple containing a list of items for the requested page and the total count of matching items. It sorts results by created_at in descending order.
from app.models.bookmark import BookmarkStatus
# List active bookmarks, 10 per page
items, total = repo.list_bookmarks(
page=1,
per_page=10,
status=BookmarkStatus.ACTIVE.value
)
print(f"Showing {len(items)} of {total} active bookmarks.")
Deleting Bookmarks
This codebase distinguishes between "hard" deletes (removing the record entirely) and "soft" deletes (moving to trash).
Hard Delete
The repository's delete_bookmark method performs a hard delete, removing the bookmark from the in-memory dictionary.
# Returns True if the bookmark existed and was removed
success = repo.delete_bookmark("some-id-123")
Soft Delete (Recommended)
Following the pattern in BookmarkService.delete_bookmark, you should typically perform a soft delete by updating the status to TRASHED and saving the change.
bookmark = repo.get_bookmark("some-id-123")
if bookmark:
bookmark.trash() # Sets status to BookmarkStatus.TRASHED
repo.save_bookmark(bookmark)
Advanced Retrieval by Tag
To find all bookmarks associated with a specific tag, use get_bookmarks_with_tag. This is useful for cleanup operations or tag-specific views.
tag_id = "python-docs"
bookmarks = repo.get_bookmarks_with_tag(tag_id)
for b in bookmarks:
print(f"Bookmark with tag {tag_id}: {b.title}")
Troubleshooting and Gotchas
In-Memory Persistence
The BookmarkRepository currently stores data in Python dictionaries (self._bookmarks). All data is lost when the application process restarts. This implementation serves as a high-performance placeholder for a future persistent database.
Status Filter Validation
In list_bookmarks, if an invalid string is passed to the status parameter, the repository catches the ValueError and ignores the filter entirely, returning bookmarks of all statuses.
# This will return ALL bookmarks because "invalid-status" is not a valid BookmarkStatus
items, total = repo.list_bookmarks(status="invalid-status")
Manual Timestamp Updates
When updating a bookmark directly via the repository, remember to call bookmark._touch() (or use the model's helper methods like archive()) to ensure the updated_at timestamp is refreshed before calling save_bookmark.
bookmark = repo.get_bookmark("id-1")
bookmark.description = "New description"
bookmark._touch() # Update the timestamp
repo.save_bookmark(bookmark)