Implement tag model
This commit is contained in:
parent
74bcc30821
commit
4a16e4d64c
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -3,6 +3,12 @@ from django.contrib.auth import get_user_model
|
||||||
from django.db import models
|
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):
|
class Bookmark(models.Model):
|
||||||
url = models.URLField()
|
url = models.URLField()
|
||||||
title = models.CharField(max_length=512)
|
title = models.CharField(max_length=512)
|
||||||
|
@ -14,6 +20,7 @@ class Bookmark(models.Model):
|
||||||
date_modified = models.DateTimeField()
|
date_modified = models.DateTimeField()
|
||||||
date_accessed = models.DateTimeField(blank=True, null=True)
|
date_accessed = models.DateTimeField(blank=True, null=True)
|
||||||
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
|
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
|
||||||
|
tags = models.ManyToManyField(Tag)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def resolved_title(self):
|
def resolved_title(self):
|
||||||
|
|
|
@ -1,11 +1,27 @@
|
||||||
from django.contrib.auth.models import User
|
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
|
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):
|
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
|
# Sanitize query params
|
||||||
if not query_string:
|
if not query_string:
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from bs4 import BeautifulSoup, Tag
|
import bs4
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
from django.contrib.auth.models import User
|
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):
|
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)
|
_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
|
link_tag = bookmark_tag.a
|
||||||
|
|
||||||
if link_tag is None:
|
if link_tag is None:
|
||||||
|
@ -34,9 +36,27 @@ def _import_bookmark_tag(bookmark_tag: Tag, user: User):
|
||||||
|
|
||||||
bookmark.save()
|
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):
|
def _get_or_create_bookmark(url: str, user: User):
|
||||||
try:
|
try:
|
||||||
return Bookmark.objects.get(url=url, owner=user)
|
return Bookmark.objects.get(url=url, owner=user)
|
||||||
except Bookmark.DoesNotExist:
|
except Bookmark.DoesNotExist:
|
||||||
return Bookmark()
|
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
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<a href="/" class="navbar-brand text-bold">
|
<a href="/" class="navbar-brand text-bold">
|
||||||
<i class="logo icon icon-link s-circle"></i>
|
<i class="logo icon icon-link s-circle"></i>
|
||||||
|
|
||||||
<h1>linkdings</h1>
|
<h1>linkding</h1>
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</section>
|
||||||
<section class="navbar-section">
|
<section class="navbar-section">
|
||||||
|
|
|
@ -130,3 +130,25 @@ STATICFILES_DIRS = [
|
||||||
os.path.join(BASE_DIR, 'bookmarks', 'styles'),
|
os.path.join(BASE_DIR, 'bookmarks', 'styles'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Logging with SQL statements
|
||||||
|
LOGGING = {
|
||||||
|
'version': 1,
|
||||||
|
'filters': {
|
||||||
|
'require_debug_true': {
|
||||||
|
'()': 'django.utils.log.RequireDebugTrue',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'handlers': {
|
||||||
|
'console': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'filters': ['require_debug_true'],
|
||||||
|
'class': 'logging.StreamHandler',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'loggers': {
|
||||||
|
'django.db.backends': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'handlers': ['console'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue