Add error handling and logging for importer

This commit is contained in:
Sascha Ißbrücker 2020-06-07 14:15:44 +02:00
parent 1ab4aa5045
commit 10fd3d89be
4 changed files with 66 additions and 21 deletions

View File

@ -1,3 +1,5 @@
import logging
from dataclasses import dataclass
from datetime import datetime from datetime import datetime
import bs4 import bs4
@ -7,14 +9,38 @@ from django.contrib.auth.models import User
from bookmarks.models import Bookmark, parse_tag_string from bookmarks.models import Bookmark, parse_tag_string
from bookmarks.services.tags import get_or_create_tags from bookmarks.services.tags import get_or_create_tags
logger = logging.getLogger(__name__)
@dataclass
class ImportResult:
total: int = 0
success: int = 0
failed: int = 0
def import_netscape_html(html: str, user: User): def import_netscape_html(html: str, user: User):
result = ImportResult()
try:
soup = BeautifulSoup(html, 'html.parser') soup = BeautifulSoup(html, 'html.parser')
except:
logging.exception('Could not read bookmarks file.')
raise
bookmark_tags = soup.find_all('dt') bookmark_tags = soup.find_all('dt')
for bookmark_tag in bookmark_tags: for bookmark_tag in bookmark_tags:
result.total = result.total + 1
try:
_import_bookmark_tag(bookmark_tag, user) _import_bookmark_tag(bookmark_tag, user)
result.success = result.success + 1
except:
shortened_bookmark_tag_str = str(bookmark_tag)[:100] + '...'
logging.exception('Error importing bookmark: ' + shortened_bookmark_tag_str)
result.failed = result.failed + 1
return result
def _import_bookmark_tag(bookmark_tag: bs4.Tag, user: User): def _import_bookmark_tag(bookmark_tag: bs4.Tag, user: User):

View File

@ -17,15 +17,17 @@
<input class="form-input" type="file" name="import_file"> <input class="form-input" type="file" name="import_file">
<input type="submit" class="input-group-btn col-2 btn btn-primary" value="Upload"> <input type="submit" class="input-group-btn col-2 btn btn-primary" value="Upload">
</div> </div>
{% if import_message %} {% if import_success_message %}
{% if import_message.level == DEFAULT_MESSAGE_LEVELS.SUCCESS %}
<div class="has-success"> <div class="has-success">
{% endif %}
{% if import_message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
<div class="has-error">
{% endif %}
<p class="form-input-hint"> <p class="form-input-hint">
{{ import_message }} {{ import_success_message }}
</p>
</div>
{% endif %}
{% if import_errors_message %}
<div class="has-error">
<p class="form-input-hint">
{{ import_errors_message }}
</p> </p>
</div> </div>
{% endif %} {% endif %}

View File

@ -1,3 +1,5 @@
import logging
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponse from django.http import HttpResponseRedirect, HttpResponse
@ -8,24 +10,38 @@ from bookmarks.queries import query_bookmarks
from bookmarks.services.exporter import export_netscape_html from bookmarks.services.exporter import export_netscape_html
from bookmarks.services.importer import import_netscape_html from bookmarks.services.importer import import_netscape_html
logger = logging.getLogger(__name__)
@login_required @login_required
def index(request): def index(request):
import_message = _find_message_with_tag(messages.get_messages(request), 'bookmark_import') 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')
return render(request, 'settings/index.html', { return render(request, 'settings/index.html', {
'import_message': import_message 'import_success_message': import_success_message,
'import_errors_message': import_errors_message,
}) })
@login_required @login_required
def bookmark_import(request): def bookmark_import(request):
try:
import_file = request.FILES.get('import_file') import_file = request.FILES.get('import_file')
if import_file is None:
messages.error(request, 'Please select a file to import.', 'bookmark_import_errors')
return HttpResponseRedirect(reverse('bookmarks:settings.index'))
try:
content = import_file.read() content = import_file.read()
import_netscape_html(content, request.user) result = import_netscape_html(content, request.user)
messages.success(request, 'Bookmarks were successfully imported.', 'bookmark_import') success_msg = str(result.success) + ' bookmarks were successfully imported.'
except Exception: messages.success(request, success_msg, 'bookmark_import_success')
messages.error(request, 'An error occurred during bookmark import.', 'bookmark_import') 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')
except:
logging.exception('Unexpected error during bookmark import')
messages.error(request, 'An error occurred during bookmark import.', 'bookmark_import_errors')
pass pass
return HttpResponseRedirect(reverse('bookmarks:settings.index')) return HttpResponseRedirect(reverse('bookmarks:settings.index'))
@ -33,6 +49,7 @@ def bookmark_import(request):
@login_required @login_required
def bookmark_export(request): def bookmark_export(request):
# noinspection PyBroadException
try: try:
bookmarks = query_bookmarks(request.user, '') bookmarks = query_bookmarks(request.user, '')
file_content = export_netscape_html(bookmarks) file_content = export_netscape_html(bookmarks)
@ -42,7 +59,7 @@ def bookmark_export(request):
response.write(file_content) response.write(file_content)
return response return response
except Exception: except:
return render(request, 'settings/index.html', { return render(request, 'settings/index.html', {
'export_error': 'An error occurred during bookmark export.' 'export_error': 'An error occurred during bookmark export.'
}) })

View File

@ -29,7 +29,7 @@ LOGGING = {
}, },
'loggers': { 'loggers': {
'django.db.backends': { 'django.db.backends': {
'level': 'DEBUG', 'level': 'ERROR', # Set to DEBUG to log all SQL calls
'handlers': ['console'], 'handlers': ['console'],
} }
} }