mirror of
https://github.com/sissbruecker/linkding.git
synced 2025-08-06 18:38:31 +02:00

* Bump Django * Render error messages in English * Remove unused USE_L10N option * Associate errors and help texts with form fields * Make checkbox inputs clickable * Change cancel button text * Fix tests
103 lines
3.8 KiB
Python
103 lines
3.8 KiB
Python
from django import forms
|
|
from django.forms.utils import ErrorList
|
|
|
|
from bookmarks.models import Bookmark, build_tag_string
|
|
from bookmarks.validators import BookmarkURLValidator
|
|
from bookmarks.type_defs import HttpRequest
|
|
from bookmarks.services.bookmarks import create_bookmark, update_bookmark
|
|
|
|
|
|
class CustomErrorList(ErrorList):
|
|
template_name = "shared/error_list.html"
|
|
|
|
|
|
class BookmarkForm(forms.ModelForm):
|
|
# Use URLField for URL
|
|
url = forms.CharField(validators=[BookmarkURLValidator()])
|
|
tag_string = forms.CharField(required=False)
|
|
# Do not require title and description as they may be empty
|
|
title = forms.CharField(max_length=512, required=False)
|
|
description = forms.CharField(required=False, widget=forms.Textarea())
|
|
unread = forms.BooleanField(required=False)
|
|
shared = forms.BooleanField(required=False)
|
|
# Hidden field that determines whether to close window/tab after saving the bookmark
|
|
auto_close = forms.CharField(required=False)
|
|
|
|
class Meta:
|
|
model = Bookmark
|
|
fields = [
|
|
"url",
|
|
"tag_string",
|
|
"title",
|
|
"description",
|
|
"notes",
|
|
"unread",
|
|
"shared",
|
|
"auto_close",
|
|
]
|
|
|
|
def __init__(self, request: HttpRequest, instance: Bookmark = None):
|
|
self.request = request
|
|
|
|
initial = None
|
|
if instance is None and request.method == "GET":
|
|
initial = {
|
|
"url": request.GET.get("url"),
|
|
"title": request.GET.get("title"),
|
|
"description": request.GET.get("description"),
|
|
"notes": request.GET.get("notes"),
|
|
"tag_string": request.GET.get("tags"),
|
|
"auto_close": "auto_close" in request.GET,
|
|
"unread": request.user_profile.default_mark_unread,
|
|
}
|
|
if instance is not None and request.method == "GET":
|
|
initial = {"tag_string": build_tag_string(instance.tag_names, " ")}
|
|
data = request.POST if request.method == "POST" else None
|
|
super().__init__(
|
|
data, instance=instance, initial=initial, error_class=CustomErrorList
|
|
)
|
|
|
|
@property
|
|
def is_auto_close(self):
|
|
return self.data.get("auto_close", False) == "True" or self.initial.get(
|
|
"auto_close", False
|
|
)
|
|
|
|
@property
|
|
def has_notes(self):
|
|
return self.initial.get("notes", None) or (
|
|
self.instance and self.instance.notes
|
|
)
|
|
|
|
def save(self, commit=False):
|
|
tag_string = convert_tag_string(self.data["tag_string"])
|
|
bookmark = super().save(commit=False)
|
|
if self.instance.pk:
|
|
return update_bookmark(bookmark, tag_string, self.request.user)
|
|
else:
|
|
return create_bookmark(bookmark, tag_string, self.request.user)
|
|
|
|
def clean_url(self):
|
|
# When creating a bookmark, the service logic prevents duplicate URLs by
|
|
# updating the existing bookmark instead, which is also communicated in
|
|
# the form's UI. When editing a bookmark, there is no assumption that
|
|
# it would update a different bookmark if the URL is a duplicate, so
|
|
# raise a validation error in that case.
|
|
url = self.cleaned_data["url"]
|
|
if self.instance.pk:
|
|
is_duplicate = (
|
|
Bookmark.objects.filter(owner=self.instance.owner, url=url)
|
|
.exclude(pk=self.instance.pk)
|
|
.exists()
|
|
)
|
|
if is_duplicate:
|
|
raise forms.ValidationError("A bookmark with this URL already exists.")
|
|
|
|
return url
|
|
|
|
|
|
def convert_tag_string(tag_string: str):
|
|
# Tag strings coming from inputs are space-separated, however services.bookmarks functions expect comma-separated
|
|
# strings
|
|
return tag_string.replace(" ", ",")
|