From 4a16e4d64c6a3c65bc8adc428fdd9120fcf5bb8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20I=C3=9Fbr=C3=BCcker?= Date: Sun, 30 Jun 2019 07:15:46 +0200 Subject: [PATCH] Implement tag model --- .../migrations/0002_auto_20190629_2303.py | 30 +++++++++++++++++++ bookmarks/models.py | 7 +++++ bookmarks/queries.py | 20 +++++++++++-- bookmarks/services/importer.py | 26 ++++++++++++++-- bookmarks/templates/bookmarks/layout.html | 2 +- siteroot/settings.py | 22 ++++++++++++++ 6 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 bookmarks/migrations/0002_auto_20190629_2303.py diff --git a/bookmarks/migrations/0002_auto_20190629_2303.py b/bookmarks/migrations/0002_auto_20190629_2303.py new file mode 100644 index 0000000..9d9a2e6 --- /dev/null +++ b/bookmarks/migrations/0002_auto_20190629_2303.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2.2 on 2019-06-29 23:03 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('bookmarks', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=64)), + ('date_added', models.DateTimeField()), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='bookmark', + name='tags', + field=models.ManyToManyField(to='bookmarks.Tag'), + ), + ] diff --git a/bookmarks/models.py b/bookmarks/models.py index 748c72e..5b1124f 100644 --- a/bookmarks/models.py +++ b/bookmarks/models.py @@ -3,6 +3,12 @@ from django.contrib.auth import get_user_model from django.db import models +class Tag(models.Model): + name = models.CharField(max_length=64) + date_added = models.DateTimeField() + owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE) + + class Bookmark(models.Model): url = models.URLField() title = models.CharField(max_length=512) @@ -14,6 +20,7 @@ class Bookmark(models.Model): date_modified = models.DateTimeField() date_accessed = models.DateTimeField(blank=True, null=True) owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE) + tags = models.ManyToManyField(Tag) @property def resolved_title(self): diff --git a/bookmarks/queries.py b/bookmarks/queries.py index 54eccf3..b79274a 100644 --- a/bookmarks/queries.py +++ b/bookmarks/queries.py @@ -1,11 +1,27 @@ from django.contrib.auth.models import User -from django.db.models import Q +from django.db.models import Q, Count, Aggregate, CharField from bookmarks.models import Bookmark +class Concat(Aggregate): + function = 'GROUP_CONCAT' + template = '%(function)s(%(distinct)s%(expressions)s)' + + def __init__(self, expression, distinct=False, **extra): + super(Concat, self).__init__( + expression, + distinct='DISTINCT ' if distinct else '', + output_field=CharField(), + **extra) + + def query_bookmarks(user: User, query_string: str): - query_set = Bookmark.objects + + # Add aggregated tag info to bookmark instances + query_set = Bookmark.objects \ + .annotate(tags_count=Count('tags')) \ + .annotate(tags_string=Concat('tags__name')) # Sanitize query params if not query_string: diff --git a/bookmarks/services/importer.py b/bookmarks/services/importer.py index d39d9b6..6fa5469 100644 --- a/bookmarks/services/importer.py +++ b/bookmarks/services/importer.py @@ -1,9 +1,11 @@ from datetime import datetime -from bs4 import BeautifulSoup, Tag +import bs4 +from bs4 import BeautifulSoup from django.contrib.auth.models import User +from django.utils import timezone -from bookmarks.models import Bookmark +from bookmarks.models import Bookmark, Tag def import_netscape_html(html: str, user: User): @@ -15,7 +17,7 @@ def import_netscape_html(html: str, user: User): _import_bookmark_tag(bookmark_tag, user) -def _import_bookmark_tag(bookmark_tag: Tag, user: User): +def _import_bookmark_tag(bookmark_tag: bs4.Tag, user: User): link_tag = bookmark_tag.a if link_tag is None: @@ -34,9 +36,27 @@ def _import_bookmark_tag(bookmark_tag: Tag, user: User): bookmark.save() + # Set tags + tag_string = link_tag['tags'] + tag_names = tag_string.strip().split(',') + + tags = [_get_or_create_tag(tag_name, user) for tag_name in tag_names] + bookmark.tags.set(tags) + bookmark.save() + def _get_or_create_bookmark(url: str, user: User): try: return Bookmark.objects.get(url=url, owner=user) except Bookmark.DoesNotExist: return Bookmark() + + +def _get_or_create_tag(name: str, user: User): + try: + return Tag.objects.get(name=name, owner=user) + except Tag.DoesNotExist: + tag = Tag(name=name, owner=user) + tag.date_added = timezone.now() + tag.save() + return tag diff --git a/bookmarks/templates/bookmarks/layout.html b/bookmarks/templates/bookmarks/layout.html index 04c028e..9f9c28c 100644 --- a/bookmarks/templates/bookmarks/layout.html +++ b/bookmarks/templates/bookmarks/layout.html @@ -15,7 +15,7 @@ -

linkdings

+

linkding