Add black code formatter

This commit is contained in:
Sascha Ißbrücker
2024-01-27 11:29:16 +01:00
parent 6775633be5
commit 98b9a9c1a0
128 changed files with 7181 additions and 4264 deletions

View File

@@ -2,15 +2,32 @@ import urllib.parse
from django.contrib.auth.decorators import login_required
from django.db.models import QuerySet
from django.http import HttpResponseRedirect, Http404, HttpResponseBadRequest, HttpResponseForbidden
from django.http import (
HttpResponseRedirect,
Http404,
HttpResponseBadRequest,
HttpResponseForbidden,
)
from django.shortcuts import render
from django.urls import reverse
from bookmarks import queries
from bookmarks.models import Bookmark, BookmarkForm, BookmarkSearch, build_tag_string
from bookmarks.services.bookmarks import create_bookmark, update_bookmark, archive_bookmark, archive_bookmarks, \
unarchive_bookmark, unarchive_bookmarks, delete_bookmarks, tag_bookmarks, untag_bookmarks, mark_bookmarks_as_read, \
mark_bookmarks_as_unread, share_bookmarks, unshare_bookmarks
from bookmarks.services.bookmarks import (
create_bookmark,
update_bookmark,
archive_bookmark,
archive_bookmarks,
unarchive_bookmark,
unarchive_bookmarks,
delete_bookmarks,
tag_bookmarks,
untag_bookmarks,
mark_bookmarks_as_read,
mark_bookmarks_as_unread,
share_bookmarks,
unshare_bookmarks,
)
from bookmarks.utils import get_safe_return_url
from bookmarks.views.partials import contexts
@@ -19,47 +36,57 @@ _default_page_size = 30
@login_required
def index(request):
if request.method == 'POST':
if request.method == "POST":
return search_action(request)
bookmark_list = contexts.ActiveBookmarkListContext(request)
tag_cloud = contexts.ActiveTagCloudContext(request)
return render(request, 'bookmarks/index.html', {
'bookmark_list': bookmark_list,
'tag_cloud': tag_cloud,
})
return render(
request,
"bookmarks/index.html",
{
"bookmark_list": bookmark_list,
"tag_cloud": tag_cloud,
},
)
@login_required
def archived(request):
if request.method == 'POST':
if request.method == "POST":
return search_action(request)
bookmark_list = contexts.ArchivedBookmarkListContext(request)
tag_cloud = contexts.ArchivedTagCloudContext(request)
return render(request, 'bookmarks/archive.html', {
'bookmark_list': bookmark_list,
'tag_cloud': tag_cloud,
})
return render(
request,
"bookmarks/archive.html",
{
"bookmark_list": bookmark_list,
"tag_cloud": tag_cloud,
},
)
def shared(request):
if request.method == 'POST':
if request.method == "POST":
return search_action(request)
bookmark_list = contexts.SharedBookmarkListContext(request)
tag_cloud = contexts.SharedTagCloudContext(request)
public_only = not request.user.is_authenticated
users = queries.query_shared_bookmark_users(request.user_profile, bookmark_list.search, public_only)
return render(request, 'bookmarks/shared.html', {
'bookmark_list': bookmark_list,
'tag_cloud': tag_cloud,
'users': users
})
users = queries.query_shared_bookmark_users(
request.user_profile, bookmark_list.search, public_only
)
return render(
request,
"bookmarks/shared.html",
{"bookmark_list": bookmark_list, "tag_cloud": tag_cloud, "users": users},
)
def search_action(request):
if 'save' in request.POST:
if "save" in request.POST:
if not request.user.is_authenticated:
return HttpResponseForbidden()
search = BookmarkSearch.from_request(request.POST)
@@ -67,56 +94,58 @@ def search_action(request):
request.user_profile.save()
# redirect to base url including new query params
search = BookmarkSearch.from_request(request.POST, request.user_profile.search_preferences)
search = BookmarkSearch.from_request(
request.POST, request.user_profile.search_preferences
)
base_url = request.path
query_params = search.query_params
query_string = urllib.parse.urlencode(query_params)
url = base_url if not query_string else base_url + '?' + query_string
url = base_url if not query_string else base_url + "?" + query_string
return HttpResponseRedirect(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(' ', ',')
return tag_string.replace(" ", ",")
@login_required
def new(request):
initial_url = request.GET.get('url')
initial_title = request.GET.get('title')
initial_description = request.GET.get('description')
initial_auto_close = 'auto_close' in request.GET
initial_url = request.GET.get("url")
initial_title = request.GET.get("title")
initial_description = request.GET.get("description")
initial_auto_close = "auto_close" in request.GET
if request.method == 'POST':
if request.method == "POST":
form = BookmarkForm(request.POST)
auto_close = form.data['auto_close']
auto_close = form.data["auto_close"]
if form.is_valid():
current_user = request.user
tag_string = convert_tag_string(form.data['tag_string'])
tag_string = convert_tag_string(form.data["tag_string"])
create_bookmark(form.save(commit=False), tag_string, current_user)
if auto_close:
return HttpResponseRedirect(reverse('bookmarks:close'))
return HttpResponseRedirect(reverse("bookmarks:close"))
else:
return HttpResponseRedirect(reverse('bookmarks:index'))
return HttpResponseRedirect(reverse("bookmarks:index"))
else:
form = BookmarkForm()
if initial_url:
form.initial['url'] = initial_url
form.initial["url"] = initial_url
if initial_title:
form.initial['title'] = initial_title
form.initial["title"] = initial_title
if initial_description:
form.initial['description'] = initial_description
form.initial["description"] = initial_description
if initial_auto_close:
form.initial['auto_close'] = 'true'
form.initial["auto_close"] = "true"
context = {
'form': form,
'auto_close': initial_auto_close,
'return_url': reverse('bookmarks:index')
"form": form,
"auto_close": initial_auto_close,
"return_url": reverse("bookmarks:index"),
}
return render(request, 'bookmarks/new.html', context)
return render(request, "bookmarks/new.html", context)
@login_required
@@ -124,34 +153,32 @@ def edit(request, bookmark_id: int):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
raise Http404('Bookmark does not exist')
return_url = get_safe_return_url(request.GET.get('return_url'), reverse('bookmarks:index'))
raise Http404("Bookmark does not exist")
return_url = get_safe_return_url(
request.GET.get("return_url"), reverse("bookmarks:index")
)
if request.method == 'POST':
if request.method == "POST":
form = BookmarkForm(request.POST, instance=bookmark)
if form.is_valid():
tag_string = convert_tag_string(form.data['tag_string'])
tag_string = convert_tag_string(form.data["tag_string"])
update_bookmark(form.save(commit=False), tag_string, request.user)
return HttpResponseRedirect(return_url)
else:
form = BookmarkForm(instance=bookmark)
form.initial['tag_string'] = build_tag_string(bookmark.tag_names, ' ')
form.initial["tag_string"] = build_tag_string(bookmark.tag_names, " ")
context = {
'form': form,
'bookmark_id': bookmark_id,
'return_url': return_url
}
context = {"form": form, "bookmark_id": bookmark_id, "return_url": return_url}
return render(request, 'bookmarks/edit.html', context)
return render(request, "bookmarks/edit.html", context)
def remove(request, bookmark_id: int):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
raise Http404('Bookmark does not exist')
raise Http404("Bookmark does not exist")
bookmark.delete()
@@ -160,7 +187,7 @@ def archive(request, bookmark_id: int):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
raise Http404('Bookmark does not exist')
raise Http404("Bookmark does not exist")
archive_bookmark(bookmark)
@@ -169,7 +196,7 @@ def unarchive(request, bookmark_id: int):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
raise Http404('Bookmark does not exist')
raise Http404("Bookmark does not exist")
unarchive_bookmark(bookmark)
@@ -178,7 +205,7 @@ def unshare(request, bookmark_id: int):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
raise Http404('Bookmark does not exist')
raise Http404("Bookmark does not exist")
bookmark.shared = False
bookmark.save()
@@ -188,7 +215,7 @@ def mark_as_read(request, bookmark_id: int):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
raise Http404('Bookmark does not exist')
raise Http404("Bookmark does not exist")
bookmark.unread = False
bookmark.save()
@@ -215,57 +242,59 @@ def shared_action(request):
def action(request, query: QuerySet[Bookmark] = None):
# Single bookmark actions
if 'archive' in request.POST:
archive(request, request.POST['archive'])
if 'unarchive' in request.POST:
unarchive(request, request.POST['unarchive'])
if 'remove' in request.POST:
remove(request, request.POST['remove'])
if 'mark_as_read' in request.POST:
mark_as_read(request, request.POST['mark_as_read'])
if 'unshare' in request.POST:
unshare(request, request.POST['unshare'])
if "archive" in request.POST:
archive(request, request.POST["archive"])
if "unarchive" in request.POST:
unarchive(request, request.POST["unarchive"])
if "remove" in request.POST:
remove(request, request.POST["remove"])
if "mark_as_read" in request.POST:
mark_as_read(request, request.POST["mark_as_read"])
if "unshare" in request.POST:
unshare(request, request.POST["unshare"])
# Bulk actions
if 'bulk_execute' in request.POST:
if "bulk_execute" in request.POST:
if query is None:
return HttpResponseBadRequest('View does not support bulk actions')
return HttpResponseBadRequest("View does not support bulk actions")
bulk_action = request.POST['bulk_action']
bulk_action = request.POST["bulk_action"]
# Determine set of bookmarks
if request.POST.get('bulk_select_across') == 'on':
if request.POST.get("bulk_select_across") == "on":
# Query full list of bookmarks across all pages
bookmark_ids = query.only('id').values_list('id', flat=True)
bookmark_ids = query.only("id").values_list("id", flat=True)
else:
# Use only selected bookmarks
bookmark_ids = request.POST.getlist('bookmark_id')
bookmark_ids = request.POST.getlist("bookmark_id")
if 'bulk_archive' == bulk_action:
if "bulk_archive" == bulk_action:
archive_bookmarks(bookmark_ids, request.user)
if 'bulk_unarchive' == bulk_action:
if "bulk_unarchive" == bulk_action:
unarchive_bookmarks(bookmark_ids, request.user)
if 'bulk_delete' == bulk_action:
if "bulk_delete" == bulk_action:
delete_bookmarks(bookmark_ids, request.user)
if 'bulk_tag' == bulk_action:
tag_string = convert_tag_string(request.POST['bulk_tag_string'])
if "bulk_tag" == bulk_action:
tag_string = convert_tag_string(request.POST["bulk_tag_string"])
tag_bookmarks(bookmark_ids, tag_string, request.user)
if 'bulk_untag' == bulk_action:
tag_string = convert_tag_string(request.POST['bulk_tag_string'])
if "bulk_untag" == bulk_action:
tag_string = convert_tag_string(request.POST["bulk_tag_string"])
untag_bookmarks(bookmark_ids, tag_string, request.user)
if 'bulk_read' == bulk_action:
if "bulk_read" == bulk_action:
mark_bookmarks_as_read(bookmark_ids, request.user)
if 'bulk_unread' == bulk_action:
if "bulk_unread" == bulk_action:
mark_bookmarks_as_unread(bookmark_ids, request.user)
if 'bulk_share' == bulk_action:
if "bulk_share" == bulk_action:
share_bookmarks(bookmark_ids, request.user)
if 'bulk_unshare' == bulk_action:
if "bulk_unshare" == bulk_action:
unshare_bookmarks(bookmark_ids, request.user)
return_url = get_safe_return_url(request.GET.get('return_url'), reverse('bookmarks:index'))
return_url = get_safe_return_url(
request.GET.get("return_url"), reverse("bookmarks:index")
)
return HttpResponseRedirect(return_url)
@login_required
def close(request):
return render(request, 'bookmarks/close.html')
return render(request, "bookmarks/close.html")

View File

@@ -6,15 +6,12 @@ from bookmarks.views.settings import app_version
def health(request):
code = 200
response = {
'version': app_version,
'status': 'healthy'
}
response = {"version": app_version, "status": "healthy"}
try:
connections['default'].ensure_connection()
connections["default"].ensure_connection()
except Exception:
response['status'] = 'unhealthy'
response["status"] = "unhealthy"
code = 500
return JsonResponse(response, status=code)

View File

@@ -7,7 +7,7 @@ def manifest(request):
"short_name": "linkding",
"start_url": "bookmarks",
"display": "standalone",
"scope": "/" + settings.LD_CONTEXT_PATH
"scope": "/" + settings.LD_CONTEXT_PATH,
}
return JsonResponse(response, status=200)

View File

@@ -8,51 +8,51 @@ from bookmarks.views.partials import contexts
def active_bookmark_list(request):
bookmark_list_context = contexts.ActiveBookmarkListContext(request)
return render(request, 'bookmarks/bookmark_list.html', {
'bookmark_list': bookmark_list_context
})
return render(
request,
"bookmarks/bookmark_list.html",
{"bookmark_list": bookmark_list_context},
)
@login_required
def active_tag_cloud(request):
tag_cloud_context = contexts.ActiveTagCloudContext(request)
return render(request, 'bookmarks/tag_cloud.html', {
'tag_cloud': tag_cloud_context
})
return render(request, "bookmarks/tag_cloud.html", {"tag_cloud": tag_cloud_context})
@login_required
def archived_bookmark_list(request):
bookmark_list_context = contexts.ArchivedBookmarkListContext(request)
return render(request, 'bookmarks/bookmark_list.html', {
'bookmark_list': bookmark_list_context
})
return render(
request,
"bookmarks/bookmark_list.html",
{"bookmark_list": bookmark_list_context},
)
@login_required
def archived_tag_cloud(request):
tag_cloud_context = contexts.ArchivedTagCloudContext(request)
return render(request, 'bookmarks/tag_cloud.html', {
'tag_cloud': tag_cloud_context
})
return render(request, "bookmarks/tag_cloud.html", {"tag_cloud": tag_cloud_context})
@login_required
def shared_bookmark_list(request):
bookmark_list_context = contexts.SharedBookmarkListContext(request)
return render(request, 'bookmarks/bookmark_list.html', {
'bookmark_list': bookmark_list_context
})
return render(
request,
"bookmarks/bookmark_list.html",
{"bookmark_list": bookmark_list_context},
)
@login_required
def shared_tag_cloud(request):
tag_cloud_context = contexts.SharedTagCloudContext(request)
return render(request, 'bookmarks/tag_cloud.html', {
'tag_cloud': tag_cloud_context
})
return render(request, "bookmarks/tag_cloud.html", {"tag_cloud": tag_cloud_context})

View File

@@ -8,7 +8,14 @@ from django.urls import reverse
from bookmarks import queries
from bookmarks import utils
from bookmarks.models import Bookmark, BookmarkSearch, BookmarkSearchForm, User, UserProfile, Tag
from bookmarks.models import (
Bookmark,
BookmarkSearch,
BookmarkSearchForm,
User,
UserProfile,
Tag,
)
DEFAULT_PAGE_SIZE = 30
@@ -34,22 +41,26 @@ class BookmarkItem:
css_classes = []
if bookmark.unread:
css_classes.append('unread')
css_classes.append("unread")
if bookmark.shared:
css_classes.append('shared')
css_classes.append("shared")
self.css_classes = ' '.join(css_classes)
self.css_classes = " ".join(css_classes)
if profile.bookmark_date_display == UserProfile.BOOKMARK_DATE_DISPLAY_RELATIVE:
self.display_date = utils.humanize_relative_date(bookmark.date_added)
elif profile.bookmark_date_display == UserProfile.BOOKMARK_DATE_DISPLAY_ABSOLUTE:
elif (
profile.bookmark_date_display == UserProfile.BOOKMARK_DATE_DISPLAY_ABSOLUTE
):
self.display_date = utils.humanize_absolute_date(bookmark.date_added)
self.show_notes_button = bookmark.notes and not profile.permanent_notes
self.show_mark_as_read = is_editable and bookmark.unread
self.show_unshare = is_editable and bookmark.shared and profile.enable_sharing
self.has_extra_actions = self.show_notes_button or self.show_mark_as_read or self.show_unshare
self.has_extra_actions = (
self.show_notes_button or self.show_mark_as_read or self.show_unshare
)
class BookmarkListContext:
@@ -58,22 +69,30 @@ class BookmarkListContext:
user_profile = request.user_profile
self.request = request
self.search = BookmarkSearch.from_request(self.request.GET, user_profile.search_preferences)
self.search = BookmarkSearch.from_request(
self.request.GET, user_profile.search_preferences
)
query_set = self.get_bookmark_query_set()
page_number = request.GET.get('page')
page_number = request.GET.get("page")
paginator = Paginator(query_set, DEFAULT_PAGE_SIZE)
bookmarks_page = paginator.get_page(page_number)
# Prefetch related objects, this avoids n+1 queries when accessing fields in templates
models.prefetch_related_objects(bookmarks_page.object_list, 'owner', 'tags')
models.prefetch_related_objects(bookmarks_page.object_list, "owner", "tags")
self.items = [BookmarkItem(bookmark, user, user_profile) for bookmark in bookmarks_page]
self.items = [
BookmarkItem(bookmark, user, user_profile) for bookmark in bookmarks_page
]
self.is_empty = paginator.count == 0
self.bookmarks_page = bookmarks_page
self.bookmarks_total = paginator.count
self.return_url = self.generate_return_url(self.search, self.get_base_url(), page_number)
self.action_url = self.generate_action_url(self.search, self.get_base_action_url(), self.return_url)
self.return_url = self.generate_return_url(
self.search, self.get_base_url(), page_number
)
self.action_url = self.generate_action_url(
self.search, self.get_base_action_url(), self.return_url
)
self.link_target = user_profile.bookmark_link_target
self.date_display = user_profile.bookmark_date_display
self.show_url = user_profile.display_url
@@ -84,69 +103,74 @@ class BookmarkListContext:
def generate_return_url(search: BookmarkSearch, base_url: str, page: int = None):
query_params = search.query_params
if page is not None:
query_params['page'] = page
query_params["page"] = page
query_string = urllib.parse.urlencode(query_params)
return base_url if query_string == '' else base_url + '?' + query_string
return base_url if query_string == "" else base_url + "?" + query_string
@staticmethod
def generate_action_url(search: BookmarkSearch, base_action_url: str, return_url: str):
def generate_action_url(
search: BookmarkSearch, base_action_url: str, return_url: str
):
query_params = search.query_params
query_params['return_url'] = return_url
query_params["return_url"] = return_url
query_string = urllib.parse.urlencode(query_params)
return base_action_url if query_string == '' else base_action_url + '?' + query_string
return (
base_action_url
if query_string == ""
else base_action_url + "?" + query_string
)
def get_base_url(self):
raise Exception(f'Must be implemented by subclass')
raise Exception(f"Must be implemented by subclass")
def get_base_action_url(self):
raise Exception(f'Must be implemented by subclass')
raise Exception(f"Must be implemented by subclass")
def get_bookmark_query_set(self):
raise Exception(f'Must be implemented by subclass')
raise Exception(f"Must be implemented by subclass")
class ActiveBookmarkListContext(BookmarkListContext):
def get_base_url(self):
return reverse('bookmarks:index')
return reverse("bookmarks:index")
def get_base_action_url(self):
return reverse('bookmarks:index.action')
return reverse("bookmarks:index.action")
def get_bookmark_query_set(self):
return queries.query_bookmarks(self.request.user,
self.request.user_profile,
self.search)
return queries.query_bookmarks(
self.request.user, self.request.user_profile, self.search
)
class ArchivedBookmarkListContext(BookmarkListContext):
def get_base_url(self):
return reverse('bookmarks:archived')
return reverse("bookmarks:archived")
def get_base_action_url(self):
return reverse('bookmarks:archived.action')
return reverse("bookmarks:archived.action")
def get_bookmark_query_set(self):
return queries.query_archived_bookmarks(self.request.user,
self.request.user_profile,
self.search)
return queries.query_archived_bookmarks(
self.request.user, self.request.user_profile, self.search
)
class SharedBookmarkListContext(BookmarkListContext):
def get_base_url(self):
return reverse('bookmarks:shared')
return reverse("bookmarks:shared")
def get_base_action_url(self):
return reverse('bookmarks:shared.action')
return reverse("bookmarks:shared.action")
def get_bookmark_query_set(self):
user = User.objects.filter(username=self.search.user).first()
public_only = not self.request.user.is_authenticated
return queries.query_shared_bookmarks(user,
self.request.user_profile,
self.search,
public_only)
return queries.query_shared_bookmarks(
user, self.request.user_profile, self.search, public_only
)
class TagGroup:
@@ -179,13 +203,17 @@ class TagCloudContext:
user_profile = request.user_profile
self.request = request
self.search = BookmarkSearch.from_request(self.request.GET, user_profile.search_preferences)
self.search = BookmarkSearch.from_request(
self.request.GET, user_profile.search_preferences
)
query_set = self.get_tag_query_set()
tags = list(query_set)
selected_tags = self.get_selected_tags(tags)
unique_tags = utils.unique(tags, key=lambda x: str.lower(x.name))
unique_selected_tags = utils.unique(selected_tags, key=lambda x: str.lower(x.name))
unique_selected_tags = utils.unique(
selected_tags, key=lambda x: str.lower(x.name)
)
has_selected_tags = len(unique_selected_tags) > 0
unselected_tags = set(unique_tags).symmetric_difference(unique_selected_tags)
groups = TagGroup.create_tag_groups(unselected_tags)
@@ -196,13 +224,13 @@ class TagCloudContext:
self.has_selected_tags = has_selected_tags
def get_tag_query_set(self):
raise Exception(f'Must be implemented by subclass')
raise Exception(f"Must be implemented by subclass")
def get_selected_tags(self, tags: List[Tag]):
parsed_query = queries.parse_query_string(self.search.q)
tag_names = parsed_query['tag_names']
tag_names = parsed_query["tag_names"]
if self.request.user_profile.tag_search == UserProfile.TAG_SEARCH_LAX:
tag_names = tag_names + parsed_query['search_terms']
tag_names = tag_names + parsed_query["search_terms"]
tag_names = [tag_name.lower() for tag_name in tag_names]
return [tag for tag in tags if tag.name.lower() in tag_names]
@@ -210,23 +238,22 @@ class TagCloudContext:
class ActiveTagCloudContext(TagCloudContext):
def get_tag_query_set(self):
return queries.query_bookmark_tags(self.request.user,
self.request.user_profile,
self.search)
return queries.query_bookmark_tags(
self.request.user, self.request.user_profile, self.search
)
class ArchivedTagCloudContext(TagCloudContext):
def get_tag_query_set(self):
return queries.query_archived_bookmark_tags(self.request.user,
self.request.user_profile,
self.search)
return queries.query_archived_bookmark_tags(
self.request.user, self.request.user_profile, self.search
)
class SharedTagCloudContext(TagCloudContext):
def get_tag_query_set(self):
user = User.objects.filter(username=self.search.user).first()
public_only = not self.request.user.is_authenticated
return queries.query_shared_bookmark_tags(user,
self.request.user_profile,
self.search,
public_only)
return queries.query_shared_bookmark_tags(
user, self.request.user_profile, self.search, public_only
)

View File

@@ -26,30 +26,40 @@ def general(request):
enable_refresh_favicons = django_settings.LD_ENABLE_REFRESH_FAVICONS
update_profile_success_message = None
refresh_favicons_success_message = None
import_success_message = _find_message_with_tag(messages.get_messages(request), 'bookmark_import_success')
import_errors_message = _find_message_with_tag(messages.get_messages(request), 'bookmark_import_errors')
import_success_message = _find_message_with_tag(
messages.get_messages(request), "bookmark_import_success"
)
import_errors_message = _find_message_with_tag(
messages.get_messages(request), "bookmark_import_errors"
)
version_info = get_version_info(get_ttl_hash())
if request.method == 'POST':
if 'update_profile' in request.POST:
if request.method == "POST":
if "update_profile" in request.POST:
profile_form = update_profile(request)
update_profile_success_message = 'Profile updated'
if 'refresh_favicons' in request.POST:
update_profile_success_message = "Profile updated"
if "refresh_favicons" in request.POST:
tasks.schedule_refresh_favicons(request.user)
refresh_favicons_success_message = 'Scheduled favicon update. This may take a while...'
refresh_favicons_success_message = (
"Scheduled favicon update. This may take a while..."
)
if not profile_form:
profile_form = UserProfileForm(instance=request.user_profile)
return render(request, 'settings/general.html', {
'form': profile_form,
'enable_refresh_favicons': enable_refresh_favicons,
'update_profile_success_message': update_profile_success_message,
'refresh_favicons_success_message': refresh_favicons_success_message,
'import_success_message': import_success_message,
'import_errors_message': import_errors_message,
'version_info': version_info,
})
return render(
request,
"settings/general.html",
{
"form": profile_form,
"enable_refresh_favicons": enable_refresh_favicons,
"update_profile_success_message": update_profile_success_message,
"refresh_favicons_success_message": refresh_favicons_success_message,
"import_success_message": import_success_message,
"import_errors_message": import_errors_message,
"version_info": version_info,
},
)
def update_profile(request):
@@ -69,21 +79,23 @@ def update_profile(request):
def get_version_info(ttl_hash=None):
latest_version = None
try:
latest_version_url = 'https://api.github.com/repos/sissbruecker/linkding/releases/latest'
latest_version_url = (
"https://api.github.com/repos/sissbruecker/linkding/releases/latest"
)
response = requests.get(latest_version_url, timeout=5)
json = response.json()
if response.status_code == 200 and 'name' in json:
latest_version = json['name'][1:]
if response.status_code == 200 and "name" in json:
latest_version = json["name"][1:]
except requests.exceptions.RequestException:
pass
latest_version_info = ''
latest_version_info = ""
if latest_version == app_version:
latest_version_info = ' (latest)'
latest_version_info = " (latest)"
elif latest_version is not None:
latest_version_info = f' (latest: {latest_version})'
latest_version_info = f" (latest: {latest_version})"
return f'{app_version}{latest_version_info}'
return f"{app_version}{latest_version_info}"
def get_ttl_hash(seconds=3600):
@@ -93,42 +105,61 @@ def get_ttl_hash(seconds=3600):
@login_required
def integrations(request):
application_url = request.build_absolute_uri(reverse('bookmarks:new'))
application_url = request.build_absolute_uri(reverse("bookmarks:new"))
api_token = Token.objects.get_or_create(user=request.user)[0]
feed_token = FeedToken.objects.get_or_create(user=request.user)[0]
all_feed_url = request.build_absolute_uri(reverse('bookmarks:feeds.all', args=[feed_token.key]))
unread_feed_url = request.build_absolute_uri(reverse('bookmarks:feeds.unread', args=[feed_token.key]))
return render(request, 'settings/integrations.html', {
'application_url': application_url,
'api_token': api_token.key,
'all_feed_url': all_feed_url,
'unread_feed_url': unread_feed_url,
})
all_feed_url = request.build_absolute_uri(
reverse("bookmarks:feeds.all", args=[feed_token.key])
)
unread_feed_url = request.build_absolute_uri(
reverse("bookmarks:feeds.unread", args=[feed_token.key])
)
return render(
request,
"settings/integrations.html",
{
"application_url": application_url,
"api_token": api_token.key,
"all_feed_url": all_feed_url,
"unread_feed_url": unread_feed_url,
},
)
@login_required
def bookmark_import(request):
import_file = request.FILES.get('import_file')
import_options = importer.ImportOptions(map_private_flag=request.POST.get('map_private_flag') == 'on')
import_file = request.FILES.get("import_file")
import_options = importer.ImportOptions(
map_private_flag=request.POST.get("map_private_flag") == "on"
)
if import_file is None:
messages.error(request, 'Please select a file to import.', 'bookmark_import_errors')
return HttpResponseRedirect(reverse('bookmarks:settings.general'))
messages.error(
request, "Please select a file to import.", "bookmark_import_errors"
)
return HttpResponseRedirect(reverse("bookmarks:settings.general"))
try:
content = import_file.read().decode()
result = importer.import_netscape_html(content, request.user, import_options)
success_msg = str(result.success) + ' bookmarks were successfully imported.'
messages.success(request, success_msg, 'bookmark_import_success')
success_msg = str(result.success) + " bookmarks were successfully imported."
messages.success(request, success_msg, "bookmark_import_success")
if result.failed > 0:
err_msg = str(result.failed) + ' bookmarks could not be imported. Please check the logs for more details.'
messages.error(request, err_msg, 'bookmark_import_errors')
err_msg = (
str(result.failed)
+ " bookmarks could not be imported. Please check the logs for more details."
)
messages.error(request, err_msg, "bookmark_import_errors")
except:
logging.exception('Unexpected error during bookmark import')
messages.error(request, 'An error occurred during bookmark import.', 'bookmark_import_errors')
logging.exception("Unexpected error during bookmark import")
messages.error(
request,
"An error occurred during bookmark import.",
"bookmark_import_errors",
)
pass
return HttpResponseRedirect(reverse('bookmarks:settings.general'))
return HttpResponseRedirect(reverse("bookmarks:settings.general"))
@login_required
@@ -137,18 +168,20 @@ def bookmark_export(request):
try:
bookmarks = Bookmark.objects.filter(owner=request.user)
# Prefetch tags to prevent n+1 queries
prefetch_related_objects(bookmarks, 'tags')
prefetch_related_objects(bookmarks, "tags")
file_content = exporter.export_netscape_html(bookmarks)
response = HttpResponse(content_type='text/plain; charset=UTF-8')
response['Content-Disposition'] = 'attachment; filename="bookmarks.html"'
response = HttpResponse(content_type="text/plain; charset=UTF-8")
response["Content-Disposition"] = 'attachment; filename="bookmarks.html"'
response.write(file_content)
return response
except:
return render(request, 'settings/general.html', {
'export_error': 'An error occurred during bookmark export.'
})
return render(
request,
"settings/general.html",
{"export_error": "An error occurred during bookmark export."},
)
def _find_message_with_tag(messages, tag):

View File

@@ -8,13 +8,15 @@ from bookmarks.utils import get_safe_return_url
@login_required
def acknowledge(request):
toast_id = request.POST['toast']
toast_id = request.POST["toast"]
try:
toast = Toast.objects.get(pk=toast_id, owner=request.user)
except Toast.DoesNotExist:
raise Http404('Toast does not exist')
raise Http404("Toast does not exist")
toast.acknowledged = True
toast.save()
return_url = get_safe_return_url(request.GET.get('return_url'), reverse('bookmarks:index'))
return_url = get_safe_return_url(
request.GET.get("return_url"), reverse("bookmarks:index")
)
return HttpResponseRedirect(return_url)