did some optimisation
This commit is contained in:
parent
c00b2b0e52
commit
58d4f27c61
@ -78,11 +78,11 @@ INSTALLED_APPS = [
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
"library",
|
||||
# 'debug_toolbar', # DEBUG purposes
|
||||
'debug_toolbar', # DEBUG purposes
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
# 'debug_toolbar.middleware.DebugToolbarMiddleware', # DEBUG purposes
|
||||
'debug_toolbar.middleware.DebugToolbarMiddleware', # DEBUG purposes
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
|
@ -30,8 +30,8 @@ urlpatterns = [
|
||||
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
|
||||
|
||||
# if settings.DEBUG: # DEBUG purposes
|
||||
# import debug_toolbar
|
||||
# urlpatterns = [
|
||||
# path('__debug__/', include(debug_toolbar.urls)),
|
||||
# ] + urlpatterns
|
||||
if settings.DEBUG: # DEBUG purposes
|
||||
import debug_toolbar
|
||||
urlpatterns = [
|
||||
path('__debug__/', include(debug_toolbar.urls)),
|
||||
] + urlpatterns
|
||||
|
107
CalibreWebCompanion/library/calibredb.py
Normal file
107
CalibreWebCompanion/library/calibredb.py
Normal file
@ -0,0 +1,107 @@
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
engine = create_engine('sqlite:///C://Users//MassiveAtoms//Documents//Calibre Library//metadata.db.', echo=True)
|
||||
Base = declarative_base(engine)
|
||||
########################################################################
|
||||
|
||||
class Author(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'authors'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, text name, sort
|
||||
|
||||
class Comment(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'comments'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, int book, text text
|
||||
|
||||
# class Data(Base): # maybe
|
||||
# """"""
|
||||
# __tablename__ = 'data'
|
||||
# __table_args__ = {'autoload':True}
|
||||
# # has int id, int book, text format, text name
|
||||
|
||||
class Identifier(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'identifiers'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, int book, text value
|
||||
|
||||
class Publisher(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'publishers'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, text name
|
||||
|
||||
class Rating(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'ratings'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, int rating
|
||||
|
||||
class Series(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'series'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, text name
|
||||
|
||||
class Tag(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'tags'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, text name
|
||||
|
||||
class Book(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'books'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, text title, text sort, time timestamp, time pubdate,
|
||||
# float series_index, text path
|
||||
|
||||
class Book_author_link(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'books_authors_link'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, id book, id author
|
||||
|
||||
class Book_publisher_link(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'books_publishers_link'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, id book, id publisher
|
||||
|
||||
class Book_rating_link(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'books_ratings_link'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, id book, id rating
|
||||
|
||||
class Book_series_link(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'books_series_link'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, id book, id series
|
||||
|
||||
class Book_tags_link(Base): # needed
|
||||
""""""
|
||||
__tablename__ = 'books_tags_link'
|
||||
__table_args__ = {'autoload':True}
|
||||
# has int id, id book, id tag
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def loadSession():
|
||||
""""""
|
||||
metadata = Base.metadata
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
return session
|
||||
|
||||
if __name__ == "__main__":
|
||||
session = loadSession()
|
||||
res = session.query(Book).all()
|
||||
for i in res:
|
||||
print(i.id, i.title, i.sort, i.timestamp, i.pubdate, i.series_index, i.path)
|
||||
|
@ -1,13 +1,22 @@
|
||||
from .models import Author, Tag, Publisher, Language, Rating, Series
|
||||
from django.db.models import Count
|
||||
|
||||
|
||||
def filters(request):
|
||||
unique_authors = Author.objects.all().order_by('sort')
|
||||
unique_tags = Tag.objects.all().order_by('name')
|
||||
unique_publishers = Publisher.objects.all().order_by('name')
|
||||
unique_languages = Language.objects.all()
|
||||
unique_ratings = Rating.objects.all().order_by('rating')
|
||||
unique_series = Series.objects.all().order_by('sort')
|
||||
# unique_authors = Author.objects.all().order_by('sort')
|
||||
# unique_tags = Tag.objects.all().order_by('name')
|
||||
# unique_publishers = Publisher.objects.all().order_by('name')
|
||||
# unique_ratings = Rating.objects.all().order_by('rating')
|
||||
# unique_languages = Language.objects.all()
|
||||
# unique_series = Series.objects.all().order_by('sort')
|
||||
# unique_authors = Author.objects.annotate(num_books=Count('book')).order_by('sort')
|
||||
unique_authors = Author.objects.only('name', "id").annotate(num_books=Count('book')).order_by('name')
|
||||
unique_tags = Tag.objects.annotate(num_books=Count('book')).order_by('name')
|
||||
unique_publishers = Publisher.objects.annotate(num_books=Count('book')).order_by('name')
|
||||
unique_languages = Language.objects.annotate(num_books=Count('book')).order_by('rating')
|
||||
unique_ratings = Rating.objects.annotate(num_books=Count('book'))
|
||||
unique_series = Series.objects.annotate(num_books=Count('book')).order_by('sort')
|
||||
|
||||
|
||||
return {
|
||||
"unique_authors": unique_authors,
|
||||
|
@ -0,0 +1,221 @@
|
||||
# Generated by Django 3.0.7 on 2020-07-11 16:22
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('library', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Author',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.TextField()),
|
||||
('sort', models.TextField(blank=True, null=True)),
|
||||
('link', models.TextField()),
|
||||
],
|
||||
options={
|
||||
'db_table': 'authors',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Book',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.TextField()),
|
||||
('sort', models.TextField(blank=True, null=True)),
|
||||
('timestamp', models.TextField(blank=True, null=True)),
|
||||
('pubdate', models.TextField(blank=True, null=True)),
|
||||
('series_index', models.FloatField()),
|
||||
('author_sort', models.TextField(blank=True, null=True)),
|
||||
('isbn', models.TextField(blank=True, null=True)),
|
||||
('lccn', models.TextField(blank=True, null=True)),
|
||||
('path', models.TextField()),
|
||||
('flags', models.IntegerField()),
|
||||
('uuid', models.TextField(blank=True, null=True)),
|
||||
('has_cover', models.BooleanField(blank=True, null=True)),
|
||||
('last_modified', models.TextField()),
|
||||
],
|
||||
options={
|
||||
'db_table': 'books',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BookAuthorLink',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'books_authors_link',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BookLanguageLink',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('item_order', models.IntegerField()),
|
||||
],
|
||||
options={
|
||||
'db_table': 'books_languages_link',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BookPublisherLink',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'books_publishers_link',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BookRatingLink',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'books_ratings_link',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BookSeriesLink',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'books_series_link',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BookTagLink',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'books_tags_link',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Comment',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('text', models.TextField()),
|
||||
],
|
||||
options={
|
||||
'db_table': 'comments',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Identifier',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('book', models.IntegerField()),
|
||||
('type', models.TextField()),
|
||||
('val', models.TextField()),
|
||||
],
|
||||
options={
|
||||
'db_table': 'identifiers',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Language',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('lang_code', models.TextField()),
|
||||
],
|
||||
options={
|
||||
'db_table': 'languages',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Publisher',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.TextField()),
|
||||
('sort', models.TextField(blank=True, null=True)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'publishers',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Rating',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('rating', models.IntegerField(blank=True, null=True)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'ratings',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Tag',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.TextField()),
|
||||
],
|
||||
options={
|
||||
'db_table': 'tags',
|
||||
'managed': False,
|
||||
},
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Authors',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Books',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='BooksAuthorsLink',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='BooksLanguagesLink',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='BooksPublishersLink',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='BooksRatingsLink',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='BooksSeriesLink',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='BooksTagsLink',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Comments',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Identifiers',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Languages',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Publishers',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Ratings',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Tags',
|
||||
),
|
||||
]
|
@ -27,12 +27,11 @@ class Author(models.Model):
|
||||
db_table = 'authors'
|
||||
|
||||
|
||||
|
||||
class Comment(models.Model):
|
||||
book = models.ForeignKey("Book", db_column="book", on_delete=models.CASCADE)
|
||||
book = models.ForeignKey("Book", db_column="book",
|
||||
on_delete=models.CASCADE)
|
||||
text = models.TextField()
|
||||
|
||||
|
||||
class Meta:
|
||||
managed = False
|
||||
db_table = 'comments'
|
||||
@ -41,7 +40,6 @@ class Comment(models.Model):
|
||||
]
|
||||
|
||||
|
||||
|
||||
class Data(models.Model):
|
||||
book = models.IntegerField()
|
||||
format = models.TextField()
|
||||
@ -98,7 +96,7 @@ class Publisher(models.Model):
|
||||
through='BookPublisherLink',
|
||||
through_fields=('publisher', 'book'),
|
||||
related_name="released"
|
||||
)
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
"""Returns the url to access a particular instance of MyModelName."""
|
||||
@ -118,6 +116,7 @@ class Publisher(models.Model):
|
||||
|
||||
class Rating(models.Model):
|
||||
rating = models.IntegerField(blank=True, null=True)
|
||||
|
||||
def get_absolute_url(self):
|
||||
"""Returns the url to access a particular instance of MyModelName."""
|
||||
return reverse('rating-detail-view', args=[str(self.id)])
|
||||
@ -153,6 +152,7 @@ class Series(models.Model):
|
||||
|
||||
class Tag(models.Model):
|
||||
name = models.TextField()
|
||||
|
||||
def get_absolute_url(self):
|
||||
"""Returns the url to access a particular instance of MyModelName."""
|
||||
return reverse('tag-detail-view', args=[str(self.id)])
|
||||
@ -193,14 +193,28 @@ class Book(models.Model):
|
||||
Language,
|
||||
through='BookLanguageLink',
|
||||
through_fields=('book', 'lang_code'))
|
||||
|
||||
@property
|
||||
def language(self):
|
||||
return self.languages.first()
|
||||
|
||||
publishers = models.ManyToManyField(
|
||||
Publisher,
|
||||
through='BookPublisherLink',
|
||||
through_fields=('book', 'publisher'))
|
||||
|
||||
@property
|
||||
def publisher(self):
|
||||
return self.publishers.first()
|
||||
|
||||
series = models.ManyToManyField(
|
||||
Series,
|
||||
through='BookSeriesLink',
|
||||
through_fields=('book', 'series'))
|
||||
|
||||
@property
|
||||
def serie(self):
|
||||
return self.series.first()
|
||||
tags = models.ManyToManyField(
|
||||
Tag,
|
||||
through='BookTagLink',
|
||||
@ -209,6 +223,11 @@ class Book(models.Model):
|
||||
Rating,
|
||||
through='BookRatingLink',
|
||||
through_fields=('book', 'rating'))
|
||||
|
||||
@property
|
||||
def rating(self):
|
||||
return self.rating.first()
|
||||
|
||||
def get_absolute_url(self):
|
||||
"""Returns the url to access a particular instance of MyModelName."""
|
||||
return reverse('book-detail-view', args=[str(self.id)])
|
||||
|
@ -39,7 +39,7 @@
|
||||
</button>
|
||||
<div class="dropdown-container">
|
||||
{% for author in unique_authors %}
|
||||
<a href="{{author.get_absolute_url}}">{{author}}</a>
|
||||
<a href="{{author.get_absolute_url}}">{{author.name}}({{author.num_books}})</a>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
@ -49,7 +49,7 @@
|
||||
</button>
|
||||
<div class="dropdown-container">
|
||||
{% for publisher in unique_publishers %}
|
||||
<a href="{{publisher.get_absolute_url}}">{{publisher}}</a>
|
||||
<a href="{{publisher.get_absolute_url}}">{{publisher}} ({{publisher.num_books}})</a>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
@ -59,7 +59,7 @@
|
||||
</button>
|
||||
<div class="dropdown-container">
|
||||
{% for rating in unique_ratings %}
|
||||
<a href="{{rating.get_absolute_url}}">{{rating}}</a>
|
||||
<a href="{{rating.get_absolute_url}}">{{rating}} ({{rating.num_books}})</a>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
@ -68,7 +68,7 @@
|
||||
</button>
|
||||
<div class="dropdown-container">
|
||||
{% for tag in unique_tags %}
|
||||
<a href="{{tag.get_absolute_url}}">{{tag}}</a>
|
||||
<a href="{{tag.get_absolute_url}}">{{tag}} ({{tag.num_books}})</a>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
40
CalibreWebCompanion/library/templates/library/results.html
Normal file
40
CalibreWebCompanion/library/templates/library/results.html
Normal file
@ -0,0 +1,40 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% load static %}
|
||||
<h1>Results</h1>
|
||||
|
||||
<table id="books">
|
||||
<tr>
|
||||
<!--When a header is clicked, run the sortTable function, with a parameter, 0 for sorting by names, 1 for sorting by country:-->
|
||||
<th onclick="sortTable(0)">Title</th>
|
||||
<th onclick="sortTable(1)">Author</th>
|
||||
<th onclick="sortTable(2)">Rating</th>
|
||||
<th onclick="sortTable(3)">Tags</th>
|
||||
<th onclick="sortTable(4)">Added</th>
|
||||
</tr>
|
||||
{% for book in book_list %}
|
||||
<tr>
|
||||
<td><a href="{{ book.get_absolute_url }}">{{ book.title }}</a></td>
|
||||
<td>{{book.author_sort}}</td>
|
||||
<td> {% for rating in book.ratings.all %}
|
||||
{{rating}}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{% for tag in book.tags.all %}
|
||||
{{tag}},
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>{{book.timestamp}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
12
README.md
12
README.md
@ -8,3 +8,15 @@ Set CALIBREPATH to the path of your library
|
||||
run `./manage.py runserver`
|
||||
|
||||
this is in development mode. don't actually use it or release it like this. The debug info it shows is spicy.
|
||||
# Features
|
||||
|
||||
- [x] Books
|
||||
- [x] navbar with tags, series, authors, etc
|
||||
- [x] Search
|
||||
- [x] authentication
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
- [ ] fix author_detail_view with annotate instead of current implementation
|
||||
|
Loading…
Reference in New Issue
Block a user