Skip to main content

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")

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)