diff --git a/bookmarks/models.py b/bookmarks/models.py index e65c2251..333c1b1d 100644 --- a/bookmarks/models.py +++ b/bookmarks/models.py @@ -168,6 +168,22 @@ def has_notes(self): self.instance and self.instance.notes ) + def clean(self): + cleaned_data = super().clean() + url = cleaned_data.get("url") + + if self.instance.pk and url: + # Ensure there is no existing Bookmark with the same URL + existing_bookmark = ( + Bookmark.objects.filter(url=url, owner=self.instance.owner) + .exclude(pk=self.instance.pk) + .first() + ) + if existing_bookmark: + self.add_error("url", "A bookmark with this URL already exists.") + + return cleaned_data + class BookmarkSearch: SORT_ADDED_ASC = "added_asc" diff --git a/bookmarks/tests/test_bookmark_edit_view.py b/bookmarks/tests/test_bookmark_edit_view.py index 18b04ec9..1ca7dba4 100644 --- a/bookmarks/tests/test_bookmark_edit_view.py +++ b/bookmarks/tests/test_bookmark_edit_view.py @@ -141,6 +141,42 @@ def test_should_prefill_bookmark_form_fields(self): html, ) + def test_should_prevent_changing_url_to_existing_url_for_same_owner(self): + edited_bookmark = self.setup_bookmark(url="http://example.com/edited") + existing_bookmark = self.setup_bookmark(url="http://example.com/existing") + + form_data = self.create_form_data( + {"id": edited_bookmark.id, "url": existing_bookmark.url} + ) + response = self.client.post( + reverse("bookmarks:edit", args=[edited_bookmark.id]), form_data + ) + + self.assertEqual(response.status_code, 422) + self.assertInHTML( + "