Compare commits

..

8 Commits

43 changed files with 710 additions and 380 deletions

View File

@ -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',

View File

@ -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

Binary file not shown.

View 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)

View File

@ -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,

View File

@ -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',
),
]

View File

@ -17,7 +17,7 @@ class Author(models.Model):
def get_absolute_url(self):
"""Returns the url to access a particular instance of MyModelName."""
return reverse('author-detail-view', args=[str(self.id)])
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.name
@ -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()
@ -61,7 +59,7 @@ class Identifier(models.Model):
book = models.IntegerField()
type = models.TextField()
val = models.TextField()
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.val
@ -77,7 +75,7 @@ class Language(models.Model):
def get_absolute_url(self):
"""Returns the url to access a particular instance of MyModelName."""
return reverse('language-detail-view', args=[str(self.lang_code)])
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.lang_code
@ -98,12 +96,12 @@ 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."""
return reverse('publisher-detail-view', args=[str(self.id)])
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.name
@ -118,10 +116,11 @@ 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)])
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return str(self.rating)
@ -138,7 +137,7 @@ class Series(models.Model):
def get_absolute_url(self):
"""Returns the url to access a particular instance of MyModelName."""
return reverse('series-detail-view', args=[str(self.id)])
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.name
@ -153,10 +152,11 @@ 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)])
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.name
@ -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,10 +223,15 @@ 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)])
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.title

View File

@ -1,112 +0,0 @@
/* sidenav */
/* Fixed sidenav, full height */
.sidenav {
height: 100%;
width: 200px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
padding-top: 20px;
}
/* Style the sidenav links and the dropdown button */
.sidenav a,
.dropdown-btn {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 20px;
color: #818181;
display: block;
border: none;
background: none;
width: 100%;
text-align: left;
cursor: pointer;
outline: none;
}
/* On mouse-over */
.sidenav a:hover,
.dropdown-btn:hover {
color: #f1f1f1;
}
/* Main content */
.main {
margin-left: 200px;
/* Same as the width of the sidenav */
font-size: 20px;
/* Increased text to enable scrolling */
padding: 0px 10px;
}
/* Add an active class to the active dropdown button */
.active {
background-color: green;
color: white;
}
/* Dropdown container (hidden by default). Optional: add a lighter background color and some left padding to change the design of the dropdown content */
.dropdown-container {
display: none;
background-color: #262626;
padding-left: 8px;
}
/* Optional: Style the caret down icon */
.fa-caret-down {
float: right;
padding-right: 8px;
}
ul.topnav {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
}
.topnav li {
float: right;
}
.topnav li a {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
.topnav li a:hover {
background-color: #111;
}
/* Table */
table {
border-spacing: 0;
width: 100%;
border: 1px solid #ddd;
}
th {
cursor: pointer;
}
th,
td {
text-align: left;
padding: 16px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}

View File

@ -1,14 +0,0 @@
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}

View File

@ -3,99 +3,126 @@
<head>
{% block title %}<title>Local Library</title>{% endblock %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<!-- Add additional CSS in static file -->
{% load static %}
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css">
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<style>
table {
width: 100%;
table-layout: fixed;
}
th {
text-align: center;
}
.title {
width: 40%;
}
.author {
width: 20%;
}
.rating {
width: 5%;
}
.tags {
width: 15%;
}
.added {
width: 20%;
}
</style>
</head>
<body>
{% block topnav%}
<ul class="topnav">
{% if user.is_authenticated %}
<li class="active"><a href="{{user.get_absolute_url}}"> {{ user.get_username }}</a></li>
<li><a href="{% url 'logout'%}?next={{request.path}}">Logout</a></li>
{% else %}
<li><a href="{% url 'sign-up'%}?next={{request.path}}">Sign up</a></li>
<li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li>
{% endif %}
</ul>
{% endblock %}
<div class="navbar-fixed">
<nav>
<div class="nav-wrapper row green darken-1">
{% if user.is_authenticated %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-2">
{% block sidebar %}
<div class="sidenav">
<a href="{% url 'search' %}">Search</a>
<a href="{% url 'books' %}">Books</a>
<button class="dropdown-btn">Authors
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
{% for author in unique_authors %}
<a href="{{author.get_absolute_url}}">{{author}}</a>
<ul class="right">
{% if user.is_authenticated %}
<li class="active"><a href="{{user.get_absolute_url}}"> {{ user.get_username }}</a></li>
<li><a href="{% url 'logout'%}?next={{request.path}}">Logout</a></li>
</ul>
{% endfor %}
</div>
<ul class="left">
<li><a href="{% url 'search' %}">Search</a></li>
<li><a href="{% url 'books' %}">Books</a></li>
<li><a class="dropdown-trigger" href="#!" data-target="dropdown-authors">Authors<i
class="material-icons right">arrow_drop_down</i></a></li>
<li><a class="dropdown-trigger" href="#!" data-target="dropdown-ratings">Ratings<i
class="material-icons right">arrow_drop_down</i></a></li>
<li><a class="dropdown-trigger" href="#!" data-target="dropdown-tags">Tags<i
class="material-icons right">arrow_drop_down</i></a></li>
</ul>
<ul id="dropdown-authors" class="dropdown-content">
{% for author in unique_authors %}
<li><a href="{{author.get_absolute_url}}">{{author}}</a></li>
{% endfor %}
</ul>
<ul id="dropdown-ratings" class="dropdown-content">
{% for rating in unique_ratings %}
<li><a href="{{rating.get_absolute_url}}">{{rating}}</a></li>
{% endfor %}
</ul>
<ul id="dropdown-tags" class="dropdown-content">
{% for tag in unique_tags %}
<li><a href="{{tag.get_absolute_url}}">{{tag}}</a></li>
{% endfor %}
</ul>
<button class="dropdown-btn">Publishers
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
{% for publisher in unique_publishers %}
<a href="{{publisher.get_absolute_url}}">{{publisher}}</a>
{% endfor %}
</div>
<button class="dropdown-btn">Ratings
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
{% for rating in unique_ratings %}
<a href="{{rating.get_absolute_url}}">{{rating}}</a>
{% endfor %}
</div>
<button class="dropdown-btn">Tags
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
{% for tag in unique_tags %}
<a href="{{tag.get_absolute_url}}">{{tag}}</a>
{% endfor %}
</div>
</div>
{% endblock %}
{% else %}
<li><a href="{% url 'sign-up'%}?next={{request.path}}">Sign up</a></li>
<li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li>
</ul>
{% endif %}
</div>
<div class="col-sm-10 ">{% block content %}{% endblock %}</div>
</div>
</nav>
</div>
<script>
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function () {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
$(".dropdown-trigger").dropdown({
hover: true,
constrainWidth: false,
coverTrigger: false
});
</script>
{% if user.is_authenticated %}
{% block content %} {% endblock %}
{% else %}
<div class="valign-wrapper" style="width:100%;height:100%;position: absolute;">
<div class="valign" style="width:100%;">
<div class="container">
<div class="row">
<div class="col s12 m6 offset-m3">
<div class="card">
<div class="card-content center">
<p>You don't have permission to view this.</p>
</div>
<div class="card-action center">
<a class="waves-effect waves-light btn-large green accent-4" href="{% url 'login'%}?next={{request.path}}">Login</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<script>
function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
@ -153,17 +180,6 @@
}
</script>
{% else %}
<h1>You don't have permission to view this.</h1>
<li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li>
or
<li><a href="{% url 'sign-up'%}?next={{request.path}}">Sign up</a></li>
{% endif %}
</body>
</html>

View File

@ -1,6 +1,22 @@
{% if user.is_authenticated %}
{% else %}
<h1>You don't have permission to view this.</h1>
<li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li>
<div class="valign-wrapper" style="width:100%;height:100%;position: absolute;">
<div class="valign" style="width:100%;">
<div class="container">
<div class="row">
<div class="col s12 m6 offset-m3">
<div class="card">
<div class="card-content center">
<p>You don't have permission to view this.</p>
</div>
<div class="card-action center">
<a class="waves-effect waves-light btn-large green accent-4" href="{% url 'login'%}?next={{request.path}}">Login</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}

View File

@ -1,17 +1,17 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<h1>{{author}}</h1>
<table id="books">
<table id="books" class="highlight centered">
<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>
<th class="title" onclick="sortTable(0)">Title</th>
<th class="author" onclick="sortTable(1)">Author</th>
<th class="rating" onclick="sortTable(2)">Rating</th>
<th class="tags" onclick="sortTable(3)">Tags</th>
<th class="added" onclick="sortTable(4)">Added</th>
</tr>
{% for book in books %}
<tr>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<h1>Author List</h1>
{% if author_list %}
<ul>

View File

@ -2,49 +2,60 @@
{% block content %}
{% load static %}
<h1>{{book.title}} by
{% if book.authors %}
{% for author in book.authors.all %}
<a href="{{author.get_absolute_url}}">{{author.name}}</a>
{%endfor%}
{% else %}
{{book.author_sort}}
{%endif%}
Published by
{% if book.publishers %}
{% for pub in book.publishers.all %}
<a href="{{pub.get_absolute_url}}">{{pub.name}}</a>
{%endfor%}
{% else %}
Unknown
{%endif%}
Tags:
{% if book.tags %}
{% for tag in book.tags.all %}
<a href="{{tag.get_absolute_url}}">{{tag.name}}</a>,
{%endfor%}
{% else %}
{%endif%}
Rating:
{% if book.ratings %}
{% for rating in book.ratings.all %}
<a href="{{rating.get_absolute_url}}">{{rating}}</a>
{%endfor%}
{% else %}
{%endif%}
<a href="{{book.publisher.get_absolute_url}}">{{book.publisher}}</a>
</h1>
<a href="{% static "" %}{{download}}"><img src="{% static "" %}{{imgpath}}" alt="download" srcset=""></a>
<div class="col s12 m7">
<div class="card z-depth-0 horizontal">
<div class="card-image">
<a style="padding-top:15%" href="{{download}}"><img src=" {% static "" %}{{imgpath}}" alt="download" srcset=""></a>
</div>
<div class="card-stacked">
<div class="card-content">
<h1> {{book.title}}</h1>
<h4> by
{% if book.authors %}
{% for author in book.authors.all %}
<a href="{{author.get_absolute_url}}">{{author.name}}</a>
{%endfor%}
{% else %}
{{book.author_sort}}
{%endif%}
<br>
Published by
{% if book.publishers %}
{% for pub in book.publishers.all %}
<a href="{{pub.get_absolute_url}}">{{pub.name}}</a>
{%endfor%}
{% else %}
Unknown
{%endif%}
<br>
Tags:
{% if book.tags %}
{% for tag in book.tags.all %}
<a href="{{tag.get_absolute_url}}">{{tag.name}}</a>,
{%endfor%}
{% else %}
{%endif%}
<br>
Rating:
{% if book.ratings %}
{% for rating in book.ratings.all %}
<a href="{{rating.get_absolute_url}}">{{rating}}</a>
{%endfor%}
{% else %}
{%endif%}
<br>
<a href="{{book.publisher.get_absolute_url}}">{{book.publisher}}</a>
</h4>
</div>
</div>
</div>
</div>
<div class="container">
{% autoescape off %}
{{comment}}
{% endautoescape %}
</div>
{% endblock %}

View File

@ -1,17 +1,21 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<h1>Book List</h1>
<table id="books">
<h1 class="center">Book List</h1>
<div class="row">
<div class="col s1 m0">
</div>
<div class="col s10 m12">
<table id="books" class="highlight centered">
<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>
<th class="title" onclick="sortTable(0)">Title</th>
<th class="author" onclick="sortTable(1)">Author</th>
<th class="rating" onclick="sortTable(2)">Rating</th>
<th class="tags" onclick="sortTable(3)">Tags</th>
<th class="added" onclick="sortTable(4)">Added</th>
</tr>
{% for book in book_list %}
<tr>
@ -30,11 +34,8 @@
</tr>
{% endfor %}
</table>
<div class="col s1 m0">
</div>
</div>
{% endblock %}

View File

@ -1,18 +1,18 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<h1>{{publisher}} </h1>
{% if publisher.released %}
<table id="books">
<table id="books" class="highlight centered">
<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>
<th class="title" onclick="sortTable(0)">Title</th>
<th class="author" onclick="sortTable(1)">Author</th>
<th class="rating" onclick="sortTable(2)">Rating</th>
<th class="tags" onclick="sortTable(3)">Tags</th>
<th class="added" onclick="sortTable(4)">Added</th>
</tr>
{% for book in books %}
<tr>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<h1>Publishers List</h1>
{% if publisher_list %}
<ul>

View File

@ -1,18 +1,17 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<h1>{{rating}}</h1>
<h1 class="left">Books with rating: {{rating}}</h1>
{% if books %}
<table id="books">
<table id="books" class="highlight centered">
<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>
<th class="title" onclick="sortTable(0)">Title</th>
<th class="author" onclick="sortTable(1)">Author</th>
<th class="rating" onclick="sortTable(2)">Rating</th>
<th class="tags" onclick="sortTable(3)">Tags</th>
<th class="added" onclick="sortTable(4)">Added</th>
</tr>
{% for book in books %}
<tr>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<h1>Ratings List</h1>
{% if rating_list %}
<ul>

View 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 %}

View File

@ -1,18 +1,17 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<h1>{{tag}}</h1>
{% if books %}
<table id="books">
<table id="books" class="highlight centered">
<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>
<th class="title" onclick="sortTable(0)">Title</th>
<th class="author" onclick="sortTable(1)">Author</th>
<th class="rating" onclick="sortTable(2)">Rating</th>
<th class="tags" onclick="sortTable(3)">Tags</th>
<th class="added" onclick="sortTable(4)">Added</th>
</tr>
{% for book in books %}
<tr>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<h1>Tags List</h1>
{% if tag_list %}
<ul>

View File

@ -2,19 +2,6 @@
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
@ -27,7 +14,23 @@
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="login" />
<div style="color:#f44336">
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
</div>
<button class="waves-effect waves-light btn green accent-4" type="submit">login</button>
<input type="hidden" name="next" value="{{ next }}" />
</form>

View File

@ -3,7 +3,7 @@
{% block content %}
<form method="post">
{% csrf_token %} {{form.as_p}} <input type="submit" value="Sign up"></form>
{% csrf_token %} {{form.as_p}} <button class="waves-effect waves-light btn green accent-4" type="submit">sign up</button></form>

View File

@ -1,17 +1,17 @@
{% 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>
<th class="title" onclick="sortTable(0)">Title</th>
<th class="author" onclick="sortTable(1)">Author</th>
<th class="rating" onclick="sortTable(2)">Rating</th>
<th class="tags" onclick="sortTable(3)">Tags</th>
<th class="added" onclick="sortTable(4)">Added</th>
</tr>
{% for book in book_list %}
<tr>

View File

@ -1,15 +1,15 @@
{% extends "base.html" %}
{% block content %}
{% load static %}
<form action="{% url 'results' %}" method="get">
<div class="container">
<form action="{% url 'results' %}" method="get" style="padding-top:2em">
<label for="title">Title: </label>
<input id="title" type="text" name="title" value="">
<label for="author">Author: </label>
<input id="author" type="text" name="author" value="">
<input type="submit" value="search">
<button class="waves-effect waves-light btn green accent-4" type="submit">search</button>
</form>
</div>
{% endblock %}

View File

@ -5,36 +5,39 @@
{% block title %}<title>Local Library</title>{% endblock %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<!-- Add additional CSS in static file -->
{% load static %}
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css">
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
</head>
<body>
{% block topnav%}
<ul class="topnav">
{% if user.is_authenticated %}
<li class="active"><a href="{{user.get_absolute_url}}"></a> {{ user.get_username }}</a></li>
<li><a href="{% url 'logout'%}?next={{request.path}}">Logout</a></li>
{% else %}
<li><a href="{% url 'sign-up'%}?next={{request.path}}">Sign up</a></li>
<li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li>
{% endif %}
</ul>
{% endblock %}
<div class="navbar-fixed">
<nav>
<div class="nav-wrapper row green darken-1">
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 ">{% block content %}{% endblock %}</div>
<ul class="right">
{% if user.is_authenticated %}
<li class="active"><a href="{{user.get_absolute_url}}"> {{ user.get_username }}</a></li>
<li><a href="{% url 'logout'%}?next={{request.path}}">Logout</a></li>
</ul>
{% else %}
<li><a href="{% url 'sign-up'%}?next={{request.path}}">Sign up</a></li>
<li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li>
</ul>
{% endif %}
</div>
</nav>
</div>
<div class="container">
<div class="row">
<div class="col s10 ">{% block content %}{% endblock %}</div>
</div>
</div>
</body>

View File

@ -7,4 +7,16 @@ Set CALIBREPATH to the path of your library
`./CalibreWebCompanion`
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.
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